All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited
@ 2019-10-21  3:37 Simon Glass
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0 Simon Glass
                   ` (87 more replies)
  0 siblings, 88 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

At present the value of the timer base is used to determine whether the
timer has been set up or not. It is true that the timer is essentially
never exactly 0 when it is read. However 'time 0' may indicate the time
that the machine was reset so it is useful to be able to denote that.

Update the code to use a separate flag instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/global_data.h | 1 +
 drivers/timer/tsc_timer.c          | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 17a4d344913..7f3ada06f61 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -76,6 +76,7 @@ struct arch_global_data {
 	uint8_t x86_mask;
 	uint32_t x86_device;
 	uint64_t tsc_base;		/* Initial value returned by rdtsc() */
+	bool tsc_inited;		/* true if tsc is ready for use */
 	unsigned long clock_rate;	/* Clock rate of timer in Hz */
 	void *new_fdt;			/* Relocated FDT */
 	uint32_t bist;			/* Built-in self test value */
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index f19d2237e4f..637c8ff25a5 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -394,7 +394,7 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count)
 
 static void tsc_timer_ensure_setup(bool early)
 {
-	if (gd->arch.tsc_base)
+	if (gd->arch.tsc_inited)
 		return;
 	gd->arch.tsc_base = rdtsc();
 
@@ -425,6 +425,7 @@ static void tsc_timer_ensure_setup(bool early)
 done:
 		gd->arch.clock_rate = fast_calibrate * 1000000;
 	}
+	gd->arch.tsc_inited = true;
 }
 
 static int tsc_timer_probe(struct udevice *dev)
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28 13:02   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT Simon Glass
                   ` (86 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

On some platforms the timer is reset to 0 when the SoC is reset. Having
this as the timer base is useful since it provides an indication of how
long it takes before U-Boot is running.

When U-Boot sets the timer base to something else, time is lost and we
no-longer have an accurate account of the time since reset. This
particularly affects bootstage.

Add an option to leave the timer base as 0 on boot.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/timer/Kconfig     | 13 +++++++++++++
 drivers/timer/tsc_timer.c |  3 ++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 5f4bc6edb67..0c922f54603 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -174,6 +174,19 @@ config X86_TSC_TIMER
 	help
 	  Select this to enable Time-Stamp Counter (TSC) timer for x86.
 
+config X86_TSC_ZERO_BASE
+	bool "Assume that TSC timer starts at 0"
+	depends on X86_TSC_TIMER
+	help
+	  On some platforms the TSC timer tick starts at the value 0 on reset.
+	  This it makes no sense to read the timer on boot and use that as the
+	  base, since we will miss some time taken to load U-Boot, etc. This
+	  delay is controlled by the SoC and we cannot reduce it, but for
+	  bootstage we want to record the time since reset as accurately as
+	  possible.
+
+	  Enable this to always us an initial TSC value of 0.
+
 config MTK_TIMER
 	bool "MediaTek timer support"
 	depends on TIMER
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index 637c8ff25a5..ac7ba7fb00d 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -396,7 +396,8 @@ static void tsc_timer_ensure_setup(bool early)
 {
 	if (gd->arch.tsc_inited)
 		return;
-	gd->arch.tsc_base = rdtsc();
+	if (!IS_ENABLED(CONFIG_X86_TSC_ZERO_BASE))
+		gd->arch.tsc_base = rdtsc();
 
 	if (!gd->arch.clock_rate) {
 		unsigned long fast_calibrate;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0 Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28  7:12   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus Simon Glass
                   ` (85 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

The x86 power unit handles power management. Support initing this device
which is modelled as a new type of system controller since there are no
operations needed.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Fix 'err-%d' typo

Changes in v2: None

 arch/x86/include/asm/cpu.h |  1 +
 arch/x86/lib/spl.c         | 40 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index feee0f915f6..21a05dab7de 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -55,6 +55,7 @@ enum {
 	X86_SYSCON_PINCONF,	/* Intel x86 pin configuration */
 	X86_SYSCON_PMU,		/* Power Management Unit */
 	X86_SYSCON_SCU,		/* System Controller Unit */
+	X86_SYSCON_PUNIT,	/* Power unit */
 };
 
 struct cpuid_result {
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 7623fc9ada0..a8eaafeb5b5 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -5,11 +5,15 @@
 
 #include <common.h>
 #include <debug_uart.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spl.h>
+#include <syscon.h>
 #include <asm/cpu.h>
+#include <asm/cpu_common.h>
 #include <asm/mrccache.h>
 #include <asm/mtrr.h>
+#include <asm/pci.h>
 #include <asm/processor.h>
 #include <asm/spl.h>
 #include <asm-generic/sections.h>
@@ -21,6 +25,32 @@ __weak int arch_cpu_init_dm(void)
 	return 0;
 }
 
+#ifdef CONFIG_TPL
+
+static int set_max_freq(void)
+{
+	if (cpu_get_burst_mode_state() == BURST_MODE_UNAVAILABLE) {
+		/*
+		 * Burst Mode has been factory-configured as disabled and is not
+		 * available in this physical processor package
+		 */
+		debug("Burst Mode is factory-disabled\n");
+		return -ENOENT;
+	}
+
+	/* Enable burst mode */
+	cpu_set_burst_mode(true);
+
+	/* Enable speed step */
+	cpu_set_eist(true);
+
+	/* Set P-State ratio */
+	cpu_set_p_state_to_turbo_ratio();
+
+	return 0;
+}
+#endif
+
 static int x86_spl_init(void)
 {
 #ifndef CONFIG_TPL
@@ -31,6 +61,8 @@ static int x86_spl_init(void)
 	 * place it immediately below CONFIG_SYS_TEXT_BASE.
 	 */
 	char *ptr = (char *)0x110000;
+#else
+	struct udevice *punit;
 #endif
 	int ret;
 
@@ -101,6 +133,14 @@ static int x86_spl_init(void)
 		return ret;
 	}
 	mtrr_commit(true);
+#else
+	ret = syscon_get_by_driver_data(X86_SYSCON_PUNIT, &punit);
+	if (ret)
+		debug("Could not find PUNIT (err=%d)\n", ret);
+
+	ret = set_max_freq();
+	if (ret)
+		debug("Failed to set CPU frequency (err=%d)\n", ret);
 #endif
 
 	return 0;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0 Simon Glass
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-21  7:52   ` Andy Shevchenko
  2019-10-28  7:12   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs Simon Glass
                   ` (84 subsequent siblings)
  87 siblings, 2 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

In TPL we try to minimise code size so do not include the PCI subsystem.
We can use fixed BARs and drivers can directly program the devices that
they need.

However we do need to bind the devices on the PCI bus and without PCI this
does not ordinarily happen. As a work-around, define a fake PCI bus which
does this binding, but no other PCI operations. This is a convenient way
to ensure that we can use the same device tree for TPL, SPL and U-Boot
proper:

   TPL    - CONFIG_TPL_PCI is not set (no auto-config, fake PCI bus)
   SPL    - CONFIG_SPL_PCI is set (no auto-config but with real PCI bus)
   U-Boot - CONFIG_PCI is set (full auto-config after relocation)

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Fix 'autoallocation' typo
- Improve wording in commit message

Changes in v2: None

 arch/x86/lib/tpl.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index d70f590541c..6ca3f7b1f20 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <debug_uart.h>
+#include <dm.h>
 #include <spl.h>
 #include <asm/cpu.h>
 #include <asm/mtrr.h>
@@ -115,3 +116,27 @@ void spl_board_init(void)
 {
 	preloader_console_init();
 }
+
+#if !CONFIG_IS_ENABLED(PCI)
+/*
+ * This is a fake PCI bus for TPL when it doesn't have proper PCI. It is enough
+ * to bind the devices on the PCI bus, some of which have early-regs properties
+ * providing fixed BARs. Individual drivers program these BARs themselves so
+ * that they can access the devices. The BARs are allocated statically in the
+ * device tree.
+ *
+ * Once SPL is running it enables PCI properly, but does not auto-assign BARs
+ * for devices, so the TPL BARs continue to be used. Once U-Boot starts it does
+ * the auto allocation (after relocation).
+ */
+static const struct udevice_id tpl_fake_pci_ids[] = {
+	{ .compatible = "pci-x86" },
+	{ }
+};
+
+U_BOOT_DRIVER(pci_x86) = {
+	.name	= "pci_x86",
+	.id	= UCLASS_SIMPLE_BUS,
+	.of_match = tpl_fake_pci_ids,
+};
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (2 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28  7:26   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 027/108] x86: Drop unnecessary cpu code for TPL Simon Glass
                   ` (83 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

Most of the timer-calibration methods are not needed on recent Intel CPUs
and just increase code size. Add an option to use the known-good way to
get the clock frequency in TPL. Size reduction is about 700 bytes.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/timer/Kconfig     | 9 +++++++++
 drivers/timer/tsc_timer.c | 7 +++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 0c922f54603..392bb5cc640 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -187,6 +187,15 @@ config X86_TSC_ZERO_BASE
 
 	  Enable this to always us an initial TSC value of 0.
 
+config TPL_X86_TSC_TIMER_NATIVE
+	bool "x86 TSC timer uses native calibration"
+	depends on TPL && X86_TSC_TIMER
+	help
+	  Selects native timer calibration for TPL and don't include the other
+	  methods in the code. This helps to reduce code size in TPL and works
+	  on fairly modern Intel chips. Code-size reductions is about 700
+	  bytes.
+
 config MTK_TIMER
 	bool "MediaTek timer support"
 	depends on TIMER
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index ac7ba7fb00d..a4f208eb2fb 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -49,8 +49,7 @@ static unsigned long native_calibrate_tsc(void)
 		return 0;
 
 	crystal_freq = tsc_info.ecx / 1000;
-
-	if (!crystal_freq) {
+	if (!CONFIG_IS_ENABLED(X86_TSC_TIMER_NATIVE) && !crystal_freq) {
 		switch (gd->arch.x86_model) {
 		case INTEL_FAM6_SKYLAKE_MOBILE:
 		case INTEL_FAM6_SKYLAKE_DESKTOP:
@@ -406,6 +405,10 @@ static void tsc_timer_ensure_setup(bool early)
 		if (fast_calibrate)
 			goto done;
 
+		/* Reduce code size by dropping other methods */
+		if (CONFIG_IS_ENABLED(X86_TSC_TIMER_NATIVE))
+			panic("no timer");
+
 		fast_calibrate = cpu_mhz_from_cpuid();
 		if (fast_calibrate)
 			goto done;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 027/108] x86: Drop unnecessary cpu code for TPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (3 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28 12:56   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 028/108] x86: Drop unnecessary interrupt " Simon Glass
                   ` (82 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

We don't need to know every detail about the CPU in TPL. Drop some
superfluous functions to reduce code size. Add a simple CPU detection
algorithm which just supports Intel and AMD, since we only support TPL
on Intel, so far.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/cpu.c      |  4 ++++
 arch/x86/cpu/i386/cpu.c | 41 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 9ee4b0294ae..4795863b33c 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -45,6 +45,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_TPL_BUILD
 static const char *const x86_vendor_name[] = {
 	[X86_VENDOR_INTEL]     = "Intel",
 	[X86_VENDOR_CYRIX]     = "Cyrix",
@@ -57,6 +58,7 @@ static const char *const x86_vendor_name[] = {
 	[X86_VENDOR_NSC]       = "NSC",
 	[X86_VENDOR_SIS]       = "SiS",
 };
+#endif
 
 int __weak x86_cleanup_before_linux(void)
 {
@@ -113,6 +115,7 @@ int icache_status(void)
 	return 1;
 }
 
+#ifndef CONFIG_TPL_BUILD
 const char *cpu_vendor_name(int vendor)
 {
 	const char *name;
@@ -123,6 +126,7 @@ const char *cpu_vendor_name(int vendor)
 
 	return name;
 }
+#endif
 
 char *cpu_get_name(char *name)
 {
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 90b546e7410..5a14d42cb26 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -20,6 +20,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <spl.h>
 #include <asm/control_regs.h>
 #include <asm/cpu.h>
 #include <asm/mp.h>
@@ -57,6 +58,8 @@ struct cpuinfo_x86 {
 	uint8_t x86_mask;
 };
 
+/* gcc 7.3 does not what to drop x86_vendors, so use #ifdef */
+#ifndef CONFIG_TPL_BUILD
 /*
  * List of cpu vendor strings along with their normalized
  * id values.
@@ -77,6 +80,7 @@ static const struct {
 	{ X86_VENDOR_NSC,       "Geode by NSC", },
 	{ X86_VENDOR_SIS,       "SiS SiS SiS ", },
 };
+#endif
 
 static void load_ds(u32 segment)
 {
@@ -229,6 +233,7 @@ static bool has_mtrr(void)
 	return cpuid_edx(0x00000001) & (1 << 12) ? true : false;
 }
 
+#ifndef CONFIG_TPL_BUILD
 static int build_vendor_name(char *vendor_name)
 {
 	struct cpuid_result result;
@@ -241,14 +246,42 @@ static int build_vendor_name(char *vendor_name)
 
 	return result.eax;
 }
+#endif
 
 static void identify_cpu(struct cpu_device_id *cpu)
 {
+	cpu->device = 0; /* fix gcc 4.4.4 warning */
+
+	/*
+	 * Do a quick and dirty check to save space - Intel and AMD only and
+	 * just the vendor. This is enough for most TPL code.
+	 */
+	if (spl_phase() == PHASE_TPL) {
+		struct cpuid_result result;
+
+		result = cpuid(0x00000000);
+		switch (result.ecx >> 24) {
+		case 'l': /* GenuineIntel */
+			cpu->vendor = X86_VENDOR_INTEL;
+			break;
+		case 'D': /* AuthenticAMD */
+			cpu->vendor = X86_VENDOR_AMD;
+			break;
+		default:
+			cpu->vendor = X86_VENDOR_ANY;
+			break;
+		}
+		if (0) /* Fix compiler warning */
+			deep_magic_nexgen_probe();
+		return;
+	}
+
+/* gcc 7.3 does not what to drop x86_vendors, so use #ifdef */
+#ifndef CONFIG_TPL_BUILD
 	char vendor_name[16];
 	int i;
 
 	vendor_name[0] = '\0'; /* Unset */
-	cpu->device = 0; /* fix gcc 4.4.4 warning */
 
 	/* Find the id and vendor_name */
 	if (!has_cpuid()) {
@@ -264,9 +297,8 @@ static void identify_cpu(struct cpu_device_id *cpu)
 		/* Detect NexGen with old hypercode */
 		else if (deep_magic_nexgen_probe())
 			memcpy(vendor_name, "NexGenDriven", 13);
-	}
-	if (has_cpuid()) {
-		int  cpuid_level;
+	} else {
+		int cpuid_level;
 
 		cpuid_level = build_vendor_name(vendor_name);
 		vendor_name[12] = '\0';
@@ -286,6 +318,7 @@ static void identify_cpu(struct cpu_device_id *cpu)
 			break;
 		}
 	}
+#endif
 }
 
 static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 028/108] x86: Drop unnecessary interrupt code for TPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (4 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 027/108] x86: Drop unnecessary cpu code for TPL Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28  7:49   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function " Simon Glass
                   ` (81 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

We don't expect an exception in TPL and don't need to print out full
details if one happens. Add a reduced version of the code for TPL.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/i386/interrupt.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c
index 1445204878c..611aab72dc7 100644
--- a/arch/x86/cpu/i386/interrupt.c
+++ b/arch/x86/cpu/i386/interrupt.c
@@ -13,6 +13,7 @@
 #include <common.h>
 #include <dm.h>
 #include <efi_loader.h>
+#include <spl.h>
 #include <asm/control_regs.h>
 #include <asm/i8259.h>
 #include <asm/interrupt.h>
@@ -22,6 +23,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_TPL_BUILD
+#define FULL_EXCEPTIONS
+#endif
+
 #define DECLARE_INTERRUPT(x) \
 	".globl irq_"#x"\n" \
 	".hidden irq_"#x"\n" \
@@ -30,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR;
 	"pushl $"#x"\n" \
 	"jmp.d32 irq_common_entry\n"
 
+#ifdef FULL_EXCEPTIONS
 static char *exceptions[] = {
 	"Divide Error",
 	"Debug",
@@ -64,7 +70,9 @@ static char *exceptions[] = {
 	"Reserved",
 	"Reserved"
 };
+#endif
 
+#ifdef FULL_EXCEPTIONS
 /**
  * show_efi_loaded_images() - show loaded UEFI images
  *
@@ -159,11 +167,16 @@ static void dump_regs(struct irq_regs *regs)
 	}
 	show_efi_loaded_images(eip);
 }
+#endif
 
 static void do_exception(struct irq_regs *regs)
 {
+#ifdef FULL_EXCEPTIONS
 	printf("%s\n", exceptions[regs->irq_id]);
 	dump_regs(regs);
+#else
+	printf("Exception %d\n", (int)regs->irq_id);
+#endif
 	hang();
 }
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function for TPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (5 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 028/108] x86: Drop unnecessary interrupt " Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28  7:50   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init() Simon Glass
                   ` (80 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

For TPL we only need to set up the features and identify the CPU to a
basic level. Add a function to handle that.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/i386/cpu.c           | 8 ++++++++
 arch/x86/include/asm/u-boot-x86.h | 9 +++++++++
 2 files changed, 17 insertions(+)

diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 5a14d42cb26..def1d797c63 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -418,6 +418,14 @@ static void setup_mtrr(void)
 	}
 }
 
+int x86_cpu_init_tpl(void)
+{
+	setup_cpu_features();
+	setup_identity();
+
+	return 0;
+}
+
 int x86_cpu_init_f(void)
 {
 	if (ll_boot_init())
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 2466ad2ad30..3e5d56d0757 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -34,6 +34,15 @@ int x86_cpu_init_f(void);
  */
 int x86_cpu_reinit_f(void);
 
+/**
+ * x86_cpu_init_tpl() - Do the minimum possible CPU init
+ *
+ * This just sets up the CPU features and figured out the identity
+ *
+ * @return 0 (indicating success, to mimic cpu_init_f())
+ */
+int x86_cpu_init_tpl(void);
+
 int cpu_init_f(void);
 void setup_gdt(struct global_data *id, u64 *gdt_addr);
 /*
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (6 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function " Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-28  7:52   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL Simon Glass
                   ` (79 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

At present we call spl_init() before identifying the CPU. This is not a
good idea - e.g. if bootstage is enabled then it will try to set up the
timer which works better if the CPU is identified.

Put explicit code at each entry pointer to identify the CPU.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/start_from_spl.S | 1 +
 arch/x86/lib/spl.c            | 4 ++++
 arch/x86/lib/tpl.c            | 5 +++++
 3 files changed, 10 insertions(+)

diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
index a73b4d7c459..22cab2dd6ce 100644
--- a/arch/x86/cpu/start_from_spl.S
+++ b/arch/x86/cpu/start_from_spl.S
@@ -31,6 +31,7 @@ _start:
 
 	call	board_init_f_init_reserve
 
+	call	x86_cpu_reinit_f
 	xorl	%eax, %eax
 	call	board_init_f
 	call	board_init_f_r
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index a8eaafeb5b5..1677f80b25c 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -67,6 +67,10 @@ static int x86_spl_init(void)
 	int ret;
 
 	debug("%s starting\n", __func__);
+	if (IS_ENABLED(TPL))
+		ret = x86_cpu_reinit_f();
+	else
+		ret = x86_cpu_init_f();
 	ret = spl_init();
 	if (ret) {
 		debug("%s: spl_init() failed\n", __func__);
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index 6ca3f7b1f20..363984f7f27 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -24,6 +24,11 @@ static int x86_tpl_init(void)
 	int ret;
 
 	debug("%s starting\n", __func__);
+	ret = x86_cpu_init_tpl();
+	if (ret) {
+		debug("%s: x86_cpu_init_tpl() failed\n", __func__);
+		return ret;
+	}
 	ret = spl_init();
 	if (ret) {
 		debug("%s: spl_init() failed\n", __func__);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (7 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init() Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-11-02  5:52   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args() Simon Glass
                   ` (78 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

We don't need to do this and it is done (in more detail) in U-Boot proper.
Drop this to save code space.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/lib/tpl.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index 363984f7f27..815849c7ff1 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -45,11 +45,6 @@ static int x86_tpl_init(void)
 		return ret;
 	}
 	preloader_console_init();
-	ret = print_cpuinfo();
-	if (ret) {
-		debug("%s: print_cpuinfo() failed\n", __func__);
-		return ret;
-	}
 
 	return 0;
 }
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (8 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-11-02  5:52   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass Simon Glass
                   ` (77 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

We already a message indicating that U-Boot is about to jump to SPL, so
make this one a debug() to reduce code size.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/lib/tpl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index 815849c7ff1..784e3a02def 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -107,7 +107,7 @@ int spl_spi_load_image(void)
 
 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
 {
-	printf("Jumping to U-Boot SPL at %lx\n", (ulong)spl_image->entry_point);
+	debug("Jumping to U-Boot SPL at %lx\n", (ulong)spl_image->entry_point);
 	jump_to_spl(spl_image->entry_point);
 	hang();
 }
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (9 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args() Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-11-02  5:52   ` Bin Meng
  2019-11-04  8:02   ` Bin Meng
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 034/108] x86: sandbox: Add a PMC emulator and test Simon Glass
                   ` (76 subsequent siblings)
  87 siblings, 2 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

Intel x86 SoCs have a power manager/controller which handles several
power-related aspects of the platform. Add a uclass for this, with a few
useful operations.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Rename power-mgr uclass to acpi-pmc

Changes in v2: None

 drivers/power/Kconfig                    |   2 +
 drivers/power/acpi_pmc/Kconfig           |  25 +++
 drivers/power/acpi_pmc/Makefile          |   5 +
 drivers/power/acpi_pmc/acpi-pmc-uclass.c | 191 +++++++++++++++++++++++
 include/dm/uclass-id.h                   |   1 +
 include/power/acpi_pmc.h                 | 185 ++++++++++++++++++++++
 6 files changed, 409 insertions(+)
 create mode 100644 drivers/power/acpi_pmc/Kconfig
 create mode 100644 drivers/power/acpi_pmc/Makefile
 create mode 100644 drivers/power/acpi_pmc/acpi-pmc-uclass.c
 create mode 100644 include/power/acpi_pmc.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 9495dca33b9..4b4f6d55568 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -4,6 +4,8 @@ source "drivers/power/domain/Kconfig"
 
 source "drivers/power/pmic/Kconfig"
 
+source "drivers/power/acpi_pmc/Kconfig"
+
 source "drivers/power/regulator/Kconfig"
 
 choice
diff --git a/drivers/power/acpi_pmc/Kconfig b/drivers/power/acpi_pmc/Kconfig
new file mode 100644
index 00000000000..472a61a9fd1
--- /dev/null
+++ b/drivers/power/acpi_pmc/Kconfig
@@ -0,0 +1,25 @@
+config ACPI_PMC
+	bool "Power Manager (x86 PMC) support"
+	help
+	  Enable support for an x86-style power-management controller which
+	  provides features including checking whether the system started from
+	  resume, powering off the system and enabling/disabling the reset
+	  mechanism.
+
+config SPL_ACPI_PMC
+	bool "Power Manager (x86 PMC) support in SPL"
+	default y if ACPI_PMC
+	help
+	  Enable support for an x86-style power-management controller which
+	  provides features including checking whether the system started from
+	  resume, powering off the system and enabling/disabling the reset
+	  mechanism.
+
+config TPL_ACPI_PMC
+	bool "Power Manager (x86 PMC) support in TPL"
+	default y if ACPI_PMC
+	help
+	  Enable support for an x86-style power-management controller which
+	  provides features including checking whether the system started from
+	  resume, powering off the system and enabling/disabling the reset
+	  mechanism.
diff --git a/drivers/power/acpi_pmc/Makefile b/drivers/power/acpi_pmc/Makefile
new file mode 100644
index 00000000000..7c1ba05c9f3
--- /dev/null
+++ b/drivers/power/acpi_pmc/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2019 Google LLC
+
+obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += acpi-pmc-uclass.o
diff --git a/drivers/power/acpi_pmc/acpi-pmc-uclass.c b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
new file mode 100644
index 00000000000..8800afecf10
--- /dev/null
+++ b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_ACPI_PMC
+
+#include <common.h>
+#include <acpi_s3.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/io.h>
+#ifdef CONFIG_CREATE_ARCH_SYMLINK
+#include <asm/arch/gpio.h>
+#endif
+#include <power/acpi_pmc.h>
+
+enum {
+	PM1_STS		= 0x00,
+	PM1_EN		= 0x02,
+	PM1_CNT		= 0x04,
+
+	GPE0_STS	= 0x20,
+	GPE0_EN		= 0x30,
+};
+
+struct tco_regs {
+	u32 tco_rld;
+	u32 tco_sts;
+	u32 tco1_cnt;
+	u32 tco_tmr;
+};
+
+enum {
+	TCO_STS_TIMEOUT			= 1 << 3,
+	TCO_STS_SECOND_TO_STS		= 1 << 17,
+	TCO1_CNT_HLT			= 1 << 11,
+};
+
+static void pmc_fill_pm_reg_info(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	int i;
+
+	upriv->pm1_sts = inw(upriv->acpi_base + PM1_STS);
+	upriv->pm1_en = inw(upriv->acpi_base + PM1_EN);
+	upriv->pm1_cnt = inw(upriv->acpi_base + PM1_CNT);
+
+	log_debug("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
+		  upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
+
+	for (i = 0; i < GPE0_REG_MAX; i++) {
+		upriv->gpe0_sts[i] = inl(upriv->acpi_base + GPE0_STS + i * 4);
+		upriv->gpe0_en[i] = inl(upriv->acpi_base + GPE0_EN + i * 4);
+		log_debug("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
+			  upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
+	}
+}
+
+int pmc_disable_tco_base(ulong tco_base)
+{
+	struct tco_regs *regs = (struct tco_regs *)tco_base;
+
+	debug("tco_base %lx = %x\n", (ulong)&regs->tco1_cnt, TCO1_CNT_HLT);
+	setio_32(&regs->tco1_cnt, TCO1_CNT_HLT);
+
+	return 0;
+}
+
+int pmc_init(struct udevice *dev)
+{
+	const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
+	int ret;
+
+	pmc_fill_pm_reg_info(dev);
+	if (!ops->init)
+		return -ENOSYS;
+
+	ret = ops->init(dev);
+	if (ret)
+		return log_msg_ret("Failed to init pmc", ret);
+
+#ifdef DEBUG
+	pmc_dump_info(dev);
+#endif
+
+	return 0;
+}
+
+int pmc_prev_sleep_state(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
+	int prev_sleep_state = ACPI_S0;	/* Default to S0 */
+
+	if (upriv->pm1_sts & WAK_STS) {
+		switch (acpi_sleep_from_pm1(upriv->pm1_cnt)) {
+		case ACPI_S3:
+			if (IS_ENABLED(HAVE_ACPI_RESUME))
+				prev_sleep_state = ACPI_S3;
+			break;
+		case ACPI_S5:
+			prev_sleep_state = ACPI_S5;
+			break;
+		default:
+			break;
+		}
+
+		/* Clear SLP_TYP */
+		outl(upriv->pm1_cnt & ~SLP_TYP, upriv->acpi_base + PM1_CNT);
+	}
+
+	if (!ops->prev_sleep_state)
+		return prev_sleep_state;
+
+	return ops->prev_sleep_state(dev, prev_sleep_state);
+}
+
+int pmc_disable_tco(struct udevice *dev)
+{
+	const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
+
+	pmc_fill_pm_reg_info(dev);
+	if (!ops->disable_tco)
+		return -ENOSYS;
+
+	return ops->disable_tco(dev);
+}
+
+int pmc_global_reset_set_enable(struct udevice *dev, bool enable)
+{
+	const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
+
+	if (!ops->global_reset_set_enable)
+		return -ENOSYS;
+
+	return ops->global_reset_set_enable(dev, enable);
+}
+
+void pmc_dump_info(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	int i;
+
+	printf("Device: %s\n", dev->name);
+	printf("ACPI base %x, pmc_bar0 %p, pmc_bar2 %p, gpe_cfg %p\n",
+	       upriv->acpi_base, upriv->pmc_bar0, upriv->pmc_bar2,
+	       upriv->gpe_cfg);
+	printf("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
+	       upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
+
+	for (i = 0; i < GPE0_REG_MAX; i++) {
+		printf("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
+		       upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
+	}
+
+	printf("prsts: %08x\n", upriv->prsts);
+	printf("tco_sts:   %04x %04x\n", upriv->tco1_sts, upriv->tco2_sts);
+	printf("gen_pmcon1: %08x gen_pmcon2: %08x gen_pmcon3: %08x\n",
+	       upriv->gen_pmcon1, upriv->gen_pmcon2, upriv->gen_pmcon3);
+}
+
+int pmc_ofdata_to_uc_platdata(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	int ret;
+
+	ret = dev_read_u32(dev, "gpe0-dwx-mask", &upriv->gpe0_dwx_mask);
+	if (ret)
+		return log_msg_ret("no gpe0-dwx-mask", ret);
+	ret = dev_read_u32(dev, "gpe0-dwx-shift-base",
+			   &upriv->gpe0_dwx_shift_base);
+	if (ret)
+		return log_msg_ret("no gpe0-dwx-shift-base", ret);
+	ret = dev_read_u32(dev, "gpe0-sts", &upriv->gpe0_sts_reg);
+	if (ret)
+		return log_msg_ret("no gpe0-sts", ret);
+	upriv->gpe0_sts_reg += upriv->acpi_base;
+	ret = dev_read_u32(dev, "gpe0-en", &upriv->gpe0_en_reg);
+	if (ret)
+		return log_msg_ret("no gpe0-en", ret);
+	upriv->gpe0_en_reg += upriv->acpi_base;
+
+	return 0;
+}
+
+UCLASS_DRIVER(acpi_pmc) = {
+	.id		= UCLASS_ACPI_PMC,
+	.name		= "power-mgr",
+	.per_device_auto_alloc_size	= sizeof(struct acpi_pmc_upriv),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index f7f323752c2..d19ad1a12e6 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -28,6 +28,7 @@ enum uclass_id {
 	UCLASS_AXI_EMUL,	/* sandbox AXI bus device emulator */
 
 	/* U-Boot uclasses start here - in alphabetical order */
+	UCLASS_ACPI_PMC,	/* (x86) Power-management controller (PMC) */
 	UCLASS_ADC,		/* Analog-to-digital converter */
 	UCLASS_AHCI,		/* SATA disk controller */
 	UCLASS_AUDIO_CODEC,	/* Audio codec with control and data path */
diff --git a/include/power/acpi_pmc.h b/include/power/acpi_pmc.h
new file mode 100644
index 00000000000..1f50c23f5f8
--- /dev/null
+++ b/include/power/acpi_pmc.h
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ACPI_PMC_H
+#define __ACPI_PMC_H
+
+enum {
+	GPE0_REG_MAX	= 4,
+};
+
+/**
+ * struct acpi_pmc_upriv - holds common data for the x86 PMC
+ *
+ * @pmc_bar0: Base address 0 of PMC
+ * @pmc_bar1: Base address 2 of PMC
+ * @acpi_base: Base address of ACPI block
+ * @pm1_sts: PM1 status
+ * @pm1_en: PM1 enable
+ * @pm1_cnt: PM1 control
+ * @gpe_cfg: Address of GPE_CFG register
+ * @gpe0_dwx_mask: Mask to use for each GPE0 (typically 7 or 0xf)
+ * @gpe0_dwx_shift_base: Base shift value to use for GPE0 (0 or 4)
+ * @gpe0_sts_req: GPE0 status register offset
+ * @gpe0_en_req: GPE0 enable register offset
+ * @gpe0_sts: GPE0 status values
+ * @gpe0_en: GPE0 enable values
+ * @gpe0_dw: GPE0 DW values
+ * @gpe0_count: Number of GPE0 registers
+ * @tco1_sts: TCO1 status
+ * @tco2_sts: TCO2 status
+ * @prsts: Power and reset status
+ * @gen_pmcon1: General power mgmt configuration 1
+ * @gen_pmcon2: General power mgmt configuration 2
+ * @gen_pmcon3: General power mgmt configuration 3
+ */
+struct acpi_pmc_upriv {
+	void *pmc_bar0;
+	void *pmc_bar2;
+	u32 acpi_base;
+	u16 pm1_sts;
+	u16 pm1_en;
+	u32 pm1_cnt;
+	u32 *gpe_cfg;
+	u32 gpe0_dwx_mask;
+	u32 gpe0_dwx_shift_base;
+	u32 gpe0_sts_reg;
+	u32 gpe0_en_reg;
+	u32 gpe0_sts[GPE0_REG_MAX];
+	u32 gpe0_en[GPE0_REG_MAX];
+	u32 gpe0_dw[GPE0_REG_MAX];
+	int gpe0_count;
+	u16 tco1_sts;
+	u16 tco2_sts;
+	u32 prsts;
+	u32 gen_pmcon1;
+	u32 gen_pmcon2;
+	u32 gen_pmcon3;
+};
+
+struct acpi_pmc_ops {
+	/**
+	 * init() - Set up the PMC for use
+	 *
+	 * This reads the current state of the PMC. Most of the state is read
+	 * automatically by the uclass since it is common.
+	 *
+	 * This is optional.
+	 *
+	 * @dev: PMC device to use
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*init)(struct udevice *dev);
+
+	/**
+	 * prev_sleep_state() - Get the previous sleep state (optional)
+	 *
+	 * This reads various state registers and returns the sleep state from
+	 * which the system woke. If this method is not provided, the uclass
+	 * will return a calculated value.
+	 *
+	 * This is optional.
+	 *
+	 * @dev: PMC device to use
+	 * @prev_sleep_state: Previous sleep state as calculated by the uclass.
+	 *	The method can use this as the return value or calculate its
+	 *	own.
+	 *
+	 * @return enum acpi_sleep_state indicating the previous sleep state
+	 *	(ACPI_S0, ACPI_S3 or ACPI_S5), or -ve on error
+	 */
+	int (*prev_sleep_state)(struct udevice *dev, int prev_sleep_state);
+
+	/**
+	 * disable_tco() - Disable the timer/counter
+	 *
+	 * Disables the timer/counter in the PMC
+	 *
+	 * This is optional.
+	 *
+	 * @dev: PMC device to use
+	 * @return 0
+	 */
+	int (*disable_tco)(struct udevice *dev);
+
+	/**
+	 * global_reset_set_enable() - Enable/Disable global reset
+	 *
+	 * Enable or disable global reset. If global reset is enabled, both hard
+	 * reset and soft reset will trigger global reset, where both host and
+	 * TXE are reset. This is cleared on cold boot, hard reset, soft reset
+	 * and Sx.
+	 *
+	 * This is optional.
+	 *
+	 * @dev: PMC device to use
+	 * @enable: true to enable global reset, false to disable
+	 * @return 0
+	 */
+	int (*global_reset_set_enable)(struct udevice *dev, bool enable);
+};
+
+#define acpi_pmc_get_ops(dev)	((struct acpi_pmc_ops *)(dev)->driver->ops)
+
+/**
+ * init() - Set up the PMC for use
+ *
+ * This reads the current state of the PMC. This reads in the common registers,
+ * then calls the device's init() method to read the SoC-specific registers.
+ *
+ * @return 0 if OK, -ve on error
+ */
+int pmc_init(struct udevice *dev);
+
+/**
+ * pmc_prev_sleep_state() - Get the previous sleep state
+ *
+ * This reads various state registers and returns the sleep state from
+ * which the system woke.
+ *
+ * @return enum acpi_sleep_state indicating the previous sleep state
+ *	(ACPI_S0, ACPI_S3 or ACPI_S5), or -ve on error
+ */
+int pmc_prev_sleep_state(struct udevice *dev);
+
+/**
+ * pmc_disable_tco() - Disable the timer/counter
+ *
+ * Disables the timer/counter in the PMC
+ *
+ * @dev: PMC device to use
+ * @return 0
+ */
+int pmc_disable_tco(struct udevice *dev);
+
+/**
+ * pmc_global_reset_set_enable() - Enable/Disable global reset
+ *
+ * Enable or disable global reset. If global reset is enabled, both hard
+ * reset and soft reset will trigger global reset, where both host and
+ * TXE are reset. This is cleared on cold boot, hard reset, soft reset
+ * and Sx.
+ *
+ * @dev: PMC device to use
+ * @enable: true to enable global reset, false to disable
+ * @return 0
+ */
+int pmc_global_reset_set_enable(struct udevice *dev, bool enable);
+
+int pmc_ofdata_to_uc_platdata(struct udevice *dev);
+
+int pmc_disable_tco_base(ulong tco_base);
+
+void pmc_dump_info(struct udevice *dev);
+
+/**
+ * pmc_gpe_init() - Set up general-purpose events
+ *
+ * @dev: PMC device
+ * @return 0 if OK, -ve on error
+ */
+int pmc_gpe_init(struct udevice *dev);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 034/108] x86: sandbox: Add a PMC emulator and test
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (10 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass Simon Glass
@ 2019-10-21  3:37 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command Simon Glass
                   ` (75 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:37 UTC (permalink / raw)
  To: u-boot

Add a simple PMC for sandbox to permit tests to run.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Rename power-mgr uclass to acpi-pmc

Changes in v2: None

 Makefile                          |   3 +-
 arch/Kconfig                      |   2 +
 arch/sandbox/dts/sandbox.dtsi     |  14 ++
 arch/sandbox/dts/test.dts         |  14 ++
 arch/sandbox/include/asm/test.h   |   1 +
 drivers/Makefile                  |   2 +
 drivers/power/acpi_pmc/Kconfig    |   9 ++
 drivers/power/acpi_pmc/Makefile   |   1 +
 drivers/power/acpi_pmc/pmc_emul.c | 246 ++++++++++++++++++++++++++++++
 drivers/power/acpi_pmc/sandbox.c  |  97 ++++++++++++
 test/dm/Makefile                  |   1 +
 test/dm/pmc.c                     |  33 ++++
 12 files changed, 422 insertions(+), 1 deletion(-)
 create mode 100644 drivers/power/acpi_pmc/pmc_emul.c
 create mode 100644 drivers/power/acpi_pmc/sandbox.c
 create mode 100644 test/dm/pmc.c

diff --git a/Makefile b/Makefile
index 3a29b5a90f9..8b102b996c0 100644
--- a/Makefile
+++ b/Makefile
@@ -725,7 +725,8 @@ libs-y += drivers/power/ \
 	drivers/power/mfd/ \
 	drivers/power/pmic/ \
 	drivers/power/battery/ \
-	drivers/power/regulator/
+	drivers/power/regulator/ \
+	drivers/power/acpi_pmc/
 libs-y += drivers/spi/
 libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/arch/Kconfig b/arch/Kconfig
index 141e48bc439..8094e186636 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -133,6 +133,8 @@ config SANDBOX
 	imply PHYLIB
 	imply DM_MDIO
 	imply DM_MDIO_MUX
+	imply ACPI_PMC
+	imply ACPI_PMC_SANDBOX
 
 config SH
 	bool "SuperH architecture"
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index f09bc70b0da..7bf144f5326 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -100,6 +100,17 @@
 	};
 
 	pci-controller {
+		pci at 1e,0 {
+			compatible = "sandbox,pmc";
+			reg = <0xf000 0 0 0 0>;
+			sandbox,emul = <&pmc_emul>;
+			gpe0-dwx-mask = <0xf>;
+			gpe0-dwx-shift-base = <4>;
+			gpe0-dw = <6 7 9>;
+			gpe0-sts = <0x20>;
+			gpe0-en = <0x30>;
+		};
+
 		pci at 1f,0 {
 			compatible = "pci-generic";
 			reg = <0xf800 0 0 0 0>;
@@ -109,6 +120,9 @@
 
 	emul {
 		compatible = "sandbox,pci-emul-parent";
+		pmc_emul: emul at 1e,0 {
+			compatible = "sandbox,pmc-emul";
+		};
 		swap_case_emul: emul at 1f,0 {
 			compatible = "sandbox,swap-case";
 		};
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 42b41fbf626..5c1093df282 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -467,6 +467,17 @@
 			       0x01000810 0 0 0 0>;
 			sandbox,emul = <&swap_case_emul0_1>;
 		};
+		pci at 1e,0 {
+			compatible = "sandbox,pmc";
+			reg = <0xf000 0 0 0 0>;
+			sandbox,emul = <&pmc_emul1e>;
+			acpi-base = <0x400>;
+			gpe0-dwx-mask = <0xf>;
+			gpe0-dwx-shift-base = <4>;
+			gpe0-dw = <6 7 9>;
+			gpe0-sts = <0x20>;
+			gpe0-en = <0x30>;
+		};
 		pci at 1f,0 {
 			compatible = "pci-generic";
 			/* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */
@@ -487,6 +498,9 @@
 		swap_case_emul0_1f: emul0 at 1f,0 {
 			compatible = "sandbox,swap-case";
 		};
+		pmc_emul1e: emul at 1e,0 {
+			compatible = "sandbox,pmc-emul";
+		};
 	};
 
 	pci1: pci-controller1 {
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index cd2b9e3155d..7f9e7fc26f5 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -13,6 +13,7 @@
 
 #define SANDBOX_PCI_VENDOR_ID		0x1234
 #define SANDBOX_PCI_SWAP_CASE_EMUL_ID	0x5678
+#define SANDBOX_PCI_PMC_EMUL_ID		0x5677
 #define SANDBOX_PCI_CLASS_CODE		PCI_CLASS_CODE_COMM
 #define SANDBOX_PCI_CLASS_SUB_CODE	PCI_CLASS_SUB_CODE_COMM_SERIAL
 
diff --git a/drivers/Makefile b/drivers/Makefile
index a4bb5e4975c..b8bdf524e08 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
 obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
 obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/
 obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/
+obj-$(CONFIG_SPL_ACPI_PMC) += power/acpi_pmc/
 obj-$(CONFIG_SPL_POWER_DOMAIN) += power/domain/
 obj-$(CONFIG_SPL_DM_RESET) += reset/
 obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/
@@ -67,6 +68,7 @@ endif
 ifdef CONFIG_TPL_BUILD
 
 obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
+obj-$(CONFIG_TPL_ACPI_PMC) += power/acpi_pmc/
 
 endif
 
diff --git a/drivers/power/acpi_pmc/Kconfig b/drivers/power/acpi_pmc/Kconfig
index 472a61a9fd1..fcd50e36cad 100644
--- a/drivers/power/acpi_pmc/Kconfig
+++ b/drivers/power/acpi_pmc/Kconfig
@@ -23,3 +23,12 @@ config TPL_ACPI_PMC
 	  provides features including checking whether the system started from
 	  resume, powering off the system and enabling/disabling the reset
 	  mechanism.
+
+config ACPI_PMC_SANDBOX
+	bool "Test power manager (PMC) for sandbox"
+	depends on ACPI_PMC && SANDBOX
+	help
+	  This driver emulates a PMC (Power-Management Controller) so that
+	  the uclass logic can be tested. You can use the 'pmc' command to
+	  access information from the driver. It uses I/O access to read
+	  from the PMC.
diff --git a/drivers/power/acpi_pmc/Makefile b/drivers/power/acpi_pmc/Makefile
index 7c1ba05c9f3..115788f109a 100644
--- a/drivers/power/acpi_pmc/Makefile
+++ b/drivers/power/acpi_pmc/Makefile
@@ -3,3 +3,4 @@
 # Copyright 2019 Google LLC
 
 obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += acpi-pmc-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC_SANDBOX) += sandbox.o pmc_emul.o
diff --git a/drivers/power/acpi_pmc/pmc_emul.c b/drivers/power/acpi_pmc/pmc_emul.c
new file mode 100644
index 00000000000..15cc7acaf33
--- /dev/null
+++ b/drivers/power/acpi_pmc/pmc_emul.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCI emulation device for an x86 Power-Management Controller (PMC)
+ *
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+#include <asm/test.h>
+#include <power/acpi_pmc.h>
+
+/**
+ * struct pmc_emul_platdata - platform data for this device
+ *
+ * @command:	Current PCI command value
+ * @bar:	Current base address values
+ */
+struct pmc_emul_platdata {
+	u16 command;
+	u32 bar[6];
+};
+
+enum {
+	MEMMAP_SIZE	= 0x80,
+};
+
+static struct pci_bar {
+	int type;
+	u32 size;
+} barinfo[] = {
+	{ PCI_BASE_ADDRESS_MEM_TYPE_32, MEMMAP_SIZE },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ PCI_BASE_ADDRESS_SPACE_IO, 256 },
+};
+
+struct pmc_emul_priv {
+	u8 regs[MEMMAP_SIZE];
+};
+
+static int sandbox_pmc_emul_read_config(struct udevice *emul, uint offset,
+					ulong *valuep, enum pci_size_t size)
+{
+	struct pmc_emul_platdata *plat = dev_get_platdata(emul);
+
+	switch (offset) {
+	case PCI_COMMAND:
+		*valuep = plat->command;
+		break;
+	case PCI_HEADER_TYPE:
+		*valuep = 0;
+		break;
+	case PCI_VENDOR_ID:
+		*valuep = SANDBOX_PCI_VENDOR_ID;
+		break;
+	case PCI_DEVICE_ID:
+		*valuep = SANDBOX_PCI_PMC_EMUL_ID;
+		break;
+	case PCI_CLASS_DEVICE:
+		if (size == PCI_SIZE_8) {
+			*valuep = SANDBOX_PCI_CLASS_SUB_CODE;
+		} else {
+			*valuep = (SANDBOX_PCI_CLASS_CODE << 8) |
+					SANDBOX_PCI_CLASS_SUB_CODE;
+		}
+		break;
+	case PCI_CLASS_CODE:
+		*valuep = SANDBOX_PCI_CLASS_CODE;
+		break;
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_1:
+	case PCI_BASE_ADDRESS_2:
+	case PCI_BASE_ADDRESS_3:
+	case PCI_BASE_ADDRESS_4:
+	case PCI_BASE_ADDRESS_5: {
+		int barnum;
+		u32 *bar;
+
+		barnum = pci_offset_to_barnum(offset);
+		bar = &plat->bar[barnum];
+
+		*valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type,
+					       barinfo[barnum].size);
+		break;
+	}
+	case PCI_CAPABILITY_LIST:
+		*valuep = PCI_CAP_ID_PM_OFFSET;
+		break;
+	}
+
+	return 0;
+}
+
+static int sandbox_pmc_emul_write_config(struct udevice *emul, uint offset,
+					 ulong value, enum pci_size_t size)
+{
+	struct pmc_emul_platdata *plat = dev_get_platdata(emul);
+
+	switch (offset) {
+	case PCI_COMMAND:
+		plat->command = value;
+		break;
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_1: {
+		int barnum;
+		u32 *bar;
+
+		barnum = pci_offset_to_barnum(offset);
+		bar = &plat->bar[barnum];
+
+		debug("w bar %d=%lx\n", barnum, value);
+		*bar = value;
+		/* space indicator (bit#0) is read-only */
+		*bar |= barinfo[barnum].type;
+		break;
+	}
+	}
+
+	return 0;
+}
+
+static int sandbox_pmc_emul_find_bar(struct udevice *emul, unsigned int addr,
+				     int *barnump, unsigned int *offsetp)
+{
+	struct pmc_emul_platdata *plat = dev_get_platdata(emul);
+	int barnum;
+
+	for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) {
+		unsigned int size = barinfo[barnum].size;
+		u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE;
+
+		if (addr >= base && addr < base + size) {
+			*barnump = barnum;
+			*offsetp = addr - base;
+			return 0;
+		}
+	}
+	*barnump = -1;
+
+	return -ENOENT;
+}
+
+static int sandbox_pmc_emul_read_io(struct udevice *dev, unsigned int addr,
+				    ulong *valuep, enum pci_size_t size)
+{
+	unsigned int offset;
+	int barnum;
+	int ret;
+
+	ret = sandbox_pmc_emul_find_bar(dev, addr, &barnum, &offset);
+	if (ret)
+		return ret;
+
+	if (barnum == 4)
+		*valuep = offset;
+	else if (barnum == 0)
+		*valuep = offset;
+
+	return 0;
+}
+
+static int sandbox_pmc_emul_write_io(struct udevice *dev, unsigned int addr,
+				     ulong value, enum pci_size_t size)
+{
+	unsigned int offset;
+	int barnum;
+	int ret;
+
+	ret = sandbox_pmc_emul_find_bar(dev, addr, &barnum, &offset);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int sandbox_pmc_emul_map_physmem(struct udevice *dev,
+					phys_addr_t addr, unsigned long *lenp,
+					void **ptrp)
+{
+	struct pmc_emul_priv *priv = dev_get_priv(dev);
+	unsigned int offset, avail;
+	int barnum;
+	int ret;
+
+	ret = sandbox_pmc_emul_find_bar(dev, addr, &barnum, &offset);
+	if (ret)
+		return ret;
+
+	if (barnum == 0) {
+		*ptrp = priv->regs + offset;
+		avail = barinfo[0].size - offset;
+		if (avail > barinfo[0].size)
+			*lenp = 0;
+		else
+			*lenp = min(*lenp, (ulong)avail);
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+static int sandbox_pmc_probe(struct udevice *dev)
+{
+	struct pmc_emul_priv *priv = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < MEMMAP_SIZE; i++)
+		priv->regs[i] = i;
+
+	return 0;
+}
+
+static struct dm_pci_emul_ops sandbox_pmc_emul_emul_ops = {
+	.read_config = sandbox_pmc_emul_read_config,
+	.write_config = sandbox_pmc_emul_write_config,
+	.read_io = sandbox_pmc_emul_read_io,
+	.write_io = sandbox_pmc_emul_write_io,
+	.map_physmem = sandbox_pmc_emul_map_physmem,
+};
+
+static const struct udevice_id sandbox_pmc_emul_ids[] = {
+	{ .compatible = "sandbox,pmc-emul" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_pmc_emul_emul) = {
+	.name		= "sandbox_pmc_emul_emul",
+	.id		= UCLASS_PCI_EMUL,
+	.of_match	= sandbox_pmc_emul_ids,
+	.ops		= &sandbox_pmc_emul_emul_ops,
+	.probe		= sandbox_pmc_probe,
+	.priv_auto_alloc_size = sizeof(struct pmc_emul_priv),
+	.platdata_auto_alloc_size = sizeof(struct pmc_emul_platdata),
+};
+
+static struct pci_device_id sandbox_pmc_emul_supported[] = {
+	{ PCI_VDEVICE(SANDBOX, SANDBOX_PCI_PMC_EMUL_ID) },
+	{},
+};
+
+U_BOOT_PCI_DEVICE(sandbox_pmc_emul_emul, sandbox_pmc_emul_supported);
diff --git a/drivers/power/acpi_pmc/sandbox.c b/drivers/power/acpi_pmc/sandbox.c
new file mode 100644
index 00000000000..7fbbf97b454
--- /dev/null
+++ b/drivers/power/acpi_pmc/sandbox.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sandbox PMC for testing
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_ACPI_PMC
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <power/acpi_pmc.h>
+
+#define GPIO_GPE_CFG		0x1050
+
+/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
+#define PRSTS			0x1000
+#define GEN_PMCON1		0x1020
+#define GEN_PMCON2		0x1024
+#define GEN_PMCON3		0x1028
+
+/* Offset of TCO registers from ACPI base I/O address */
+#define TCO_REG_OFFSET		0x60
+#define TCO1_STS	0x64
+#define TCO2_STS	0x66
+#define TCO1_CNT	0x68
+#define TCO2_CNT	0x6a
+
+struct sandbox_pmc_priv {
+	ulong base;
+};
+
+static int sandbox_pmc_fill_power_state(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+	upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS);
+	upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS);
+
+	upriv->prsts = readl(upriv->pmc_bar0 + PRSTS);
+	upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1);
+	upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2);
+	upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3);
+
+	return 0;
+}
+
+static int sandbox_prev_sleep_state(struct udevice *dev, int prev_sleep_state)
+{
+	return prev_sleep_state;
+}
+
+static int sandbox_disable_tco(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+	pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET);
+
+	return 0;
+}
+
+static int sandbox_pmc_probe(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	struct udevice *bus;
+	ulong base;
+
+	uclass_first_device(UCLASS_PCI, &bus);
+	base = dm_pci_read_bar32(dev, 0);
+	if (base == FDT_ADDR_T_NONE)
+		return log_msg_ret("No base address", -EINVAL);
+	upriv->pmc_bar0 = map_sysmem(base, 0x2000);
+	upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG);
+
+	return pmc_ofdata_to_uc_platdata(dev);
+}
+
+static struct acpi_pmc_ops sandbox_pmc_ops = {
+	.init			= sandbox_pmc_fill_power_state,
+	.prev_sleep_state	= sandbox_prev_sleep_state,
+	.disable_tco		= sandbox_disable_tco,
+};
+
+static const struct udevice_id sandbox_pmc_ids[] = {
+	{ .compatible = "sandbox,pmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(pmc_sandbox) = {
+	.name = "pmc_sandbox",
+	.id = UCLASS_ACPI_PMC,
+	.of_match = sandbox_pmc_ids,
+	.probe = sandbox_pmc_probe,
+	.ops = &sandbox_pmc_ops,
+	.priv_auto_alloc_size = sizeof(struct sandbox_pmc_priv),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 0c2fd5cb5e2..10a19a00c90 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o
 obj-$(CONFIG_PCH) += pch.o
 obj-$(CONFIG_PHY) += phy.o
 obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
+obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PWM) += pwm.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/pmc.c b/test/dm/pmc.c
new file mode 100644
index 00000000000..1a222838ab5
--- /dev/null
+++ b/test/dm/pmc.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for power-management controller uclass (PMC)
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <power/acpi_pmc.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Base test of the PMC uclass */
+static int dm_test_pmc_base(struct unit_test_state *uts)
+{
+	struct acpi_pmc_upriv *upriv;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_ACPI_PMC, &dev));
+
+	ut_assertok(pmc_disable_tco(dev));
+	ut_assertok(pmc_init(dev));
+	ut_assertok(pmc_prev_sleep_state(dev));
+
+	/* Check some values to see that I/O works */
+	upriv = dev_get_uclass_priv(dev);
+	ut_asserteq(0x24, upriv->gpe0_sts[1]);
+	ut_asserteq(0x64, upriv->tco1_sts);
+
+	return 0;
+}
+DM_TEST(dm_test_pmc_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (11 preceding siblings ...)
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 034/108] x86: sandbox: Add a PMC emulator and test Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  7:48   ` Andy Shevchenko
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass Simon Glass
                   ` (74 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add a simple command to show information about the PMC.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Rename power-mgr uclass to acpi-pmc

Changes in v2: None

 arch/Kconfig |  1 +
 cmd/Kconfig  |  8 ++++++
 cmd/Makefile |  1 +
 cmd/pmc.c    | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+)
 create mode 100644 cmd/pmc.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 8094e186636..e1f1fcd275b 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -135,6 +135,7 @@ config SANDBOX
 	imply DM_MDIO_MUX
 	imply ACPI_PMC
 	imply ACPI_PMC_SANDBOX
+	imply CMD_PMC
 
 config SH
 	bool "SuperH architecture"
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07060c63a7e..135b38b0260 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -228,6 +228,14 @@ config CMD_LICENSE
 	help
 	  Print GPL license text
 
+config CMD_PMC
+	bool "pmc"
+	help
+	  Provides access to the Intel Power-Management Controller (PMC) so
+	  that its state can be examined. This does not currently support
+	  changing the state but it is still useful for debugging and seeing
+	  what is going on.
+
 config CMD_REGINFO
 	bool "reginfo"
 	depends on PPC
diff --git a/cmd/Makefile b/cmd/Makefile
index ac843b4b16a..8151ba8741f 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -108,6 +108,7 @@ ifdef CONFIG_PCI
 obj-$(CONFIG_CMD_PCI) += pci.o
 endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
+obj-$(CONFIG_CMD_PMC) += pmc.o
 obj-$(CONFIG_CMD_PXE) += pxe.o
 obj-$(CONFIG_CMD_WOL) += wol.o
 obj-$(CONFIG_CMD_QFW) += qfw.o
diff --git a/cmd/pmc.c b/cmd/pmc.c
new file mode 100644
index 00000000000..cafeba9fccd
--- /dev/null
+++ b/cmd/pmc.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel PMC command
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <power/acpi_pmc.h>
+
+static int get_pmc_dev(struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev);
+	if (ret) {
+		printf("Could not find device (err=%d)\n", ret);
+		return ret;
+	}
+	ret = pmc_init(dev);
+	if (ret) {
+		printf("Could not init device (err=%d)\n", ret);
+		return ret;
+	}
+	*devp = dev;
+
+	return 0;
+}
+
+static int do_pmc_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = get_pmc_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	return 0;
+}
+
+static int do_pmc_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = get_pmc_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+	pmc_dump_info(dev);
+
+	return 0;
+}
+
+static cmd_tbl_t cmd_pmc_sub[] = {
+	U_BOOT_CMD_MKENT(init, 0, 1, do_pmc_init, "", ""),
+	U_BOOT_CMD_MKENT(info, 0, 1, do_pmc_info, "", ""),
+};
+
+static int do_pmc(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	const cmd_tbl_t *cp;
+
+	if (argc < 2) /* no subcommand */
+		return cmd_usage(cmdtp);
+
+	cp = find_cmd_tbl(argv[1], &cmd_pmc_sub[0], ARRAY_SIZE(cmd_pmc_sub));
+	if (!cp)
+		return CMD_RET_USAGE;
+
+	return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+	pmc, 2, 1, do_pmc, "Power-management controller info",
+	"info - read state and show info about the PMC\n"
+	"pmc init - read state from the PMC\n"
+	);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (12 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04  8:23   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 037/108] sandbox: Add PCI driver and test for p2sb Simon Glass
                   ` (73 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

The Primary-to-Sideband bus (P2SB) is used to access various peripherals
through memory-mapped I/O in a large chunk of PCI space. The space is
segmented into different channels and peripherals are accessed by
device-specific means within those channels. Devices should be added in
the device tree as subnodes of the p2sb.

This adds a uclass and enables it for sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 configs/sandbox_defconfig     |   1 +
 configs/sandbox_spl_defconfig |   1 +
 drivers/misc/Kconfig          |  33 ++++++
 drivers/misc/Makefile         |   1 +
 drivers/misc/p2sb-uclass.c    | 209 ++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h        |   1 +
 include/p2sb.h                | 127 +++++++++++++++++++++
 7 files changed, 373 insertions(+)
 create mode 100644 drivers/misc/p2sb-uclass.c
 create mode 100644 include/p2sb.h

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 20ebc68997b..f8b78b8d7e1 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -150,6 +150,7 @@ CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_SANDBOX=y
+CONFIG_P2SB=y
 CONFIG_PHY=y
 CONFIG_PHY_SANDBOX=y
 CONFIG_PINCTRL=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 409b8a38d5e..c49e05ec319 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -135,6 +135,7 @@ CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_SANDBOX=y
+CONFIG_P2SB=y
 CONFIG_PHY=y
 CONFIG_PHY_SANDBOX=y
 CONFIG_PINCTRL=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ba50893b432..1ed2e5d4aa2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -217,6 +217,39 @@ config NUVOTON_NCT6102D
 	  disable the legacy UART, the watchdog or other devices
 	  in the Nuvoton Super IO chips on X86 platforms.
 
+config P2SB
+	bool "Intel Primary-to-Sideband Bus"
+	depends on X86 || SANDBOX
+	help
+	  This enables support for the Intel Primary-to-Sideband bus,
+	  abbreviated to P2SB. The P2SB is used to access various peripherals
+	  such as eSPI, GPIO, through memory-mapped I/O in a large chunk of PCI
+	  space. The space is segmented into different channels and peripherals
+	  are accessed by device-specific means within those channels. Devices
+	  should be added in the device tree as subnodes of the P2SB. A
+	  Peripheral Channel Register? (PCR) API is provided to access those
+	  devices - see pcr_readl(), etc.
+
+config SPL_P2SB
+	bool "Intel Primary-to-Sideband Bus in SPL"
+	depends on SPL && (X86 || SANDBOX)
+	help
+	  The Primary-to-Sideband bus is used to access various peripherals
+	  through memory-mapped I/O in a large chunk of PCI space. The space is
+	  segmented into different channels and peripherals are accessed by
+	  device-specific means within those channels. Devices should be added
+	  in the device tree as subnodes of the p2sb.
+
+config TPL_P2SB
+	bool "Intel Primary-to-Sideband Bus in TPL"
+	depends on TPL && (X86 || SANDBOX)
+	help
+	  The Primary-to-Sideband bus is used to access various peripherals
+	  through memory-mapped I/O in a large chunk of PCI space. The space is
+	  segmented into different channels and peripherals are accessed by
+	  device-specific means within those channels. Devices should be added
+	  in the device tree as subnodes of the p2sb.
+
 config PWRSEQ
 	bool "Enable power-sequencing drivers"
 	depends on DM
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 0001d105bae..840d9fa5e39 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
 obj-$(CONFIG_NS87308) += ns87308.o
 obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
+obj-$(CONFIG_P2SB) += p2sb-uclass.o
 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
 obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
 obj-$(CONFIG_QFW) += qfw.o
diff --git a/drivers/misc/p2sb-uclass.c b/drivers/misc/p2sb-uclass.c
new file mode 100644
index 00000000000..c4e663b5492
--- /dev/null
+++ b/drivers/misc/p2sb-uclass.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Uclass for Primary-to-sideband bus, used to access various peripherals
+ *
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <p2sb.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <dm/uclass-internal.h>
+
+#define PCR_COMMON_IOSF_1_0	1
+
+static void *_pcr_reg_address(struct udevice *dev, uint offset)
+{
+	struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
+	struct udevice *p2sb = dev_get_parent(dev);
+	struct p2sb_uc_priv *upriv = dev_get_uclass_priv(p2sb);
+	uintptr_t reg_addr;
+
+	/* Create an address based off of port id and offset */
+	reg_addr = upriv->mmio_base;
+	reg_addr += pplat->pid << PCR_PORTID_SHIFT;
+	reg_addr += offset;
+
+	return map_sysmem(reg_addr, 4);
+}
+
+/*
+ * The mapping of addresses via the SBREG_BAR assumes the IOSF-SB
+ * agents are using 32-bit aligned accesses for their configuration
+ * registers. For IOSF versions greater than 1_0, IOSF-SB
+ * agents can use any access (8/16/32 bit aligned) for their
+ * configuration registers
+ */
+static inline void check_pcr_offset_align(uint offset, uint size)
+{
+	const size_t align = PCR_COMMON_IOSF_1_0 ? sizeof(uint32_t) : size;
+
+	assert(IS_ALIGNED(offset, align));
+}
+
+uint pcr_read32(struct udevice *dev, uint offset)
+{
+	void *ptr;
+	uint val;
+
+	/* Ensure the PCR offset is correctly aligned */
+	assert(IS_ALIGNED(offset, sizeof(uint32_t)));
+
+	ptr = _pcr_reg_address(dev, offset);
+	val = readl(ptr);
+	unmap_sysmem(ptr);
+
+	return val;
+}
+
+uint pcr_read16(struct udevice *dev, uint offset)
+{
+	/* Ensure the PCR offset is correctly aligned */
+	check_pcr_offset_align(offset, sizeof(uint16_t));
+
+	return readw(_pcr_reg_address(dev, offset));
+}
+
+uint pcr_read8(struct udevice *dev, uint offset)
+{
+	/* Ensure the PCR offset is correctly aligned */
+	check_pcr_offset_align(offset, sizeof(uint8_t));
+
+	return readb(_pcr_reg_address(dev, offset));
+}
+
+/*
+ * After every write one needs to perform a 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.
+ */
+static void write_completion(struct udevice *dev, uint offset)
+{
+	readl(_pcr_reg_address(dev, ALIGN_DOWN(offset, sizeof(uint32_t))));
+}
+
+void pcr_write32(struct udevice *dev, uint offset, uint indata)
+{
+	/* Ensure the PCR offset is correctly aligned */
+	assert(IS_ALIGNED(offset, sizeof(indata)));
+
+	writel(indata, _pcr_reg_address(dev, offset));
+	/* Ensure the writes complete */
+	write_completion(dev, offset);
+}
+
+void pcr_write16(struct udevice *dev, uint offset, uint indata)
+{
+	/* Ensure the PCR offset is correctly aligned */
+	check_pcr_offset_align(offset, sizeof(uint16_t));
+
+	writew(indata, _pcr_reg_address(dev, offset));
+	/* Ensure the writes complete */
+	write_completion(dev, offset);
+}
+
+void pcr_write8(struct udevice *dev, uint offset, uint indata)
+{
+	/* Ensure the PCR offset is correctly aligned */
+	check_pcr_offset_align(offset, sizeof(uint8_t));
+
+	writeb(indata, _pcr_reg_address(dev, offset));
+	/* Ensure the writes complete */
+	write_completion(dev, offset);
+}
+
+void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set)
+{
+	uint data32;
+
+	data32 = pcr_read32(dev, offset);
+	data32 &= ~clr;
+	data32 |= set;
+	pcr_write32(dev, offset, data32);
+}
+
+void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set)
+{
+	uint data16;
+
+	data16 = pcr_read16(dev, offset);
+	data16 &= ~clr;
+	data16 |= set;
+	pcr_write16(dev, offset, data16);
+}
+
+void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set)
+{
+	uint data8;
+
+	data8 = pcr_read8(dev, offset);
+	data8 &= ~clr;
+	data8 |= set;
+	pcr_write8(dev, offset, data8);
+}
+
+int p2sb_set_port_id(struct udevice *dev, int portid)
+{
+	struct udevice *ps2b;
+	struct p2sb_child_platdata *pplat;
+
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA))
+		return -ENOSYS;
+
+	uclass_find_first_device(UCLASS_P2SB, &ps2b);
+	if (!ps2b)
+		return -EDEADLK;
+	dev->parent = ps2b;
+
+	/*
+	 * We must allocate this, since when the device was bound it did not
+	 * have a parent.
+	 * TODO(sjg at chromium.org): Add a parent pointer to child devices in dtoc
+	 */
+	dev->parent_platdata = malloc(sizeof(*pplat));
+	if (!dev->parent_platdata)
+		return -ENOMEM;
+	pplat = dev_get_parent_platdata(dev);
+	pplat->pid = portid;
+
+	return 0;
+}
+
+static int p2sb_child_post_bind(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
+	int ret;
+	u32 pid;
+
+	ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
+	if (ret)
+		return ret;
+	pplat->pid = pid;
+#endif
+
+	return 0;
+}
+
+static int p2sb_post_bind(struct udevice *dev)
+{
+	if (spl_phase() >= PHASE_SPL && !CONFIG_IS_ENABLED(OF_PLATDATA))
+		return dm_scan_fdt_dev(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(p2sb) = {
+	.id		= UCLASS_P2SB,
+	.name		= "p2sb",
+	.per_device_auto_alloc_size = sizeof(struct p2sb_uc_priv),
+	.post_bind	= p2sb_post_bind,
+	.child_post_bind = p2sb_child_post_bind,
+	.per_child_platdata_auto_alloc_size =
+		sizeof(struct p2sb_child_platdata),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index d19ad1a12e6..6ae9138ca3d 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -70,6 +70,7 @@ enum uclass_id {
 	UCLASS_NOP,		/* No-op devices */
 	UCLASS_NORTHBRIDGE,	/* Intel Northbridge / SDRAM controller */
 	UCLASS_NVME,		/* NVM Express device */
+	UCLASS_P2SB,		/* (x86) Primary-to-Sideband Bus */
 	UCLASS_PANEL,		/* Display panel, such as an LCD */
 	UCLASS_PANEL_BACKLIGHT,	/* Backlight controller for panel */
 	UCLASS_PCH,		/* x86 platform controller hub */
diff --git a/include/p2sb.h b/include/p2sb.h
new file mode 100644
index 00000000000..370f127058c
--- /dev/null
+++ b/include/p2sb.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __p2sb_h
+#define __p2sb_h
+
+/* Port Id lives in bits 23:16 and register offset lives in 15:0 of address */
+#define PCR_PORTID_SHIFT	16
+
+/**
+ * struct p2sb_child_platdata - Information about each child of a p2sb device
+ *
+ * @pid: Port ID for this child
+ */
+struct p2sb_child_platdata {
+	uint pid;
+};
+
+/**
+ * struct p2sb_uc_priv - information for the uclass about each device
+ *
+ * This must be set up by the driver when it is probed
+ *
+ * @mmio_base: Base address of P2SB region
+ */
+struct p2sb_uc_priv {
+	uint mmio_base;
+};
+
+/**
+ * struct p2sb_ops - Operations for the P2SB (none at present)
+ */
+struct p2sb_ops {
+};
+
+#define p2sb_get_ops(dev)        ((struct p2sb_ops *)(dev)->driver->ops)
+
+/**
+ * pcr_read32/16/8() - Read from a PCR device
+ *
+ * Reads data from a PCR device within the P2SB
+ *
+ * @dev: Device to read from
+ * @offset: Offset within device to read
+ * @return value read
+ */
+uint pcr_read32(struct udevice *dev, uint offset);
+uint pcr_read16(struct udevice *dev, uint offset);
+uint pcr_read8(struct udevice *dev, uint offset);
+
+/**
+ * pcr_read32/16/8() - Write to a PCR device
+ *
+ * Writes data to a PCR device within the P2SB
+ *
+ * @dev: Device to write to
+ * @offset: Offset within device to write
+ * @data: Data to write
+ */
+void pcr_write32(struct udevice *dev, uint offset, uint data);
+void pcr_write16(struct udevice *dev, uint offset, uint data);
+void pcr_write8(struct udevice *dev, uint offset, uint data);
+
+/**
+ * pcr_clrsetbits32/16/8() - Update a PCR device
+ *
+ * Updates dat in a PCR device within the P2SB
+ *
+ * This reads from the device, clears and set bits, then writes back.
+ *
+ * new_data = (old_data & ~clr) | set
+ *
+ * @dev: Device to update
+ * @offset: Offset within device to update
+ * @clr: Bits to clear after reading
+ * @set: Bits to set before writing
+ */
+void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set);
+void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set);
+void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set);
+
+static inline void pcr_setbits32(struct udevice *dev, uint offset, uint set)
+{
+	return pcr_clrsetbits32(dev, offset, 0, set);
+}
+
+static inline void pcr_setbits16(struct udevice *dev, uint offset, uint set)
+{
+	return pcr_clrsetbits16(dev, offset, 0, set);
+}
+
+static inline void pcr_setbits8(struct udevice *dev, uint offset, uint set)
+{
+	return pcr_clrsetbits8(dev, offset, 0, set);
+}
+
+static inline void pcr_clrbits32(struct udevice *dev, uint offset, uint clr)
+{
+	return pcr_clrsetbits32(dev, offset, clr, 0);
+}
+
+static inline void pcr_clrbits16(struct udevice *dev, uint offset, uint clr)
+{
+	return pcr_clrsetbits16(dev, offset, clr, 0);
+}
+
+static inline void pcr_clrbits8(struct udevice *dev, uint offset, uint clr)
+{
+	return pcr_clrsetbits8(dev, offset, clr, 0);
+}
+
+/**
+ * p2sb_set_port_id() - Set the port ID for a p2sb child device
+ *
+ * This must be called in a device's bind() method when OF_PLATDATA is used
+ * since the uclass cannot access the device's of-platdata.
+ *
+ * @dev: Child device (whose parent is UCLASS_P2SB)
+ * @portid: Port ID of child device
+ * @return 0 if OK, -ENODEV is the p2sb device could not be found
+ */
+int p2sb_set_port_id(struct udevice *dev, int portid);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 037/108] sandbox: Add PCI driver and test for p2sb
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (13 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04  8:36   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 038/108] x86: Move UCLASS_IRQ into a separate file Simon Glass
                   ` (72 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add a sandbox driver and PCI-device emulator for p2sb. Also add a test
which uses a simple 'adder' driver to test the p2sb functionality.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Fix build errors in sandbox_spl, etc

Changes in v2: None

 arch/sandbox/cpu/state.c           |   1 +
 arch/sandbox/dts/test.dts          |  13 ++
 arch/sandbox/include/asm/test.h    |  10 ++
 configs/sandbox64_defconfig        |   2 +
 configs/sandbox_flattree_defconfig |   3 +
 configs/sandbox_spl_defconfig      |   2 +
 configs/tools-only_defconfig       |   2 +
 drivers/core/uclass.c              |   4 +-
 drivers/misc/Makefile              |   2 +
 drivers/misc/p2sb_emul.c           | 272 +++++++++++++++++++++++++++++
 drivers/misc/p2sb_sandbox.c        |  44 +++++
 drivers/misc/sandbox_adder.c       |  60 +++++++
 test/dm/Makefile                   |   1 +
 test/dm/p2sb.c                     |  28 +++
 14 files changed, 442 insertions(+), 2 deletions(-)
 create mode 100644 drivers/misc/p2sb_emul.c
 create mode 100644 drivers/misc/p2sb_sandbox.c
 create mode 100644 drivers/misc/sandbox_adder.c
 create mode 100644 test/dm/p2sb.c

diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index dee5fde4f73..cd46e000f5e 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -356,6 +356,7 @@ void state_reset_for_test(struct sandbox_state *state)
 	/* No reset yet, so mark it as such. Always allow power reset */
 	state->last_sysreset = SYSRESET_COUNT;
 	state->sysreset_allowed[SYSRESET_POWER_OFF] = true;
+	state->allow_memio = false;
 
 	memset(&state->wdt, '\0', sizeof(state->wdt));
 	memset(state->spi, '\0', sizeof(state->spi));
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5c1093df282..24631770544 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -467,6 +467,16 @@
 			       0x01000810 0 0 0 0>;
 			sandbox,emul = <&swap_case_emul0_1>;
 		};
+		p2sb-pci at 2,0 {
+			compatible = "sandbox,p2sb";
+			reg = <0x02001010 0 0 0 0>;
+			sandbox,emul = <&p2sb_emul>;
+
+			adder {
+				intel,p2sb-port-id = <3>;
+				compatible = "sandbox,adder";
+			};
+		};
 		pci at 1e,0 {
 			compatible = "sandbox,pmc";
 			reg = <0xf000 0 0 0 0>;
@@ -498,6 +508,9 @@
 		swap_case_emul0_1f: emul0 at 1f,0 {
 			compatible = "sandbox,swap-case";
 		};
+		p2sb_emul: emul at 2,0 {
+			compatible = "sandbox,p2sb-emul";
+		};
 		pmc_emul1e: emul at 1e,0 {
 			compatible = "sandbox,pmc-emul";
 		};
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 7f9e7fc26f5..77fff529e19 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -14,6 +14,7 @@
 #define SANDBOX_PCI_VENDOR_ID		0x1234
 #define SANDBOX_PCI_SWAP_CASE_EMUL_ID	0x5678
 #define SANDBOX_PCI_PMC_EMUL_ID		0x5677
+#define SANDBOX_PCI_P2SB_EMUL_ID	0x5676
 #define SANDBOX_PCI_CLASS_CODE		PCI_CLASS_CODE_COMM
 #define SANDBOX_PCI_CLASS_SUB_CODE	PCI_CLASS_SUB_CODE_COMM_SERIAL
 
@@ -214,4 +215,13 @@ int sandbox_get_pci_ep_irq_count(struct udevice *dev);
  */
 uint sandbox_pci_read_bar(u32 barval, int type, uint size);
 
+/**
+ * sandbox_set_enable_memio() - Enable memory-mapped I/O read/write
+ *
+ * Normally readl(), writel() and the like are nops on sandbox. If this function
+ * is called with true, those function do real memory accesses. This is useful
+ * for certain tests.
+ */
+void sandbox_set_enable_memio(bool enable);
+
 #endif
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 1fea683d892..4c86141ffb1 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -81,6 +81,8 @@ CONFIG_DEVRES=y
 CONFIG_DEBUG_DEVRES=y
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
 CONFIG_CLK=y
 CONFIG_CPU=y
 CONFIG_DM_DEMO=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 898815fe531..230d65b14a7 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -65,6 +65,8 @@ CONFIG_DEVRES=y
 CONFIG_DEBUG_DEVRES=y
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
 CONFIG_CLK=y
 CONFIG_CLK_COMPOSITE_CCF=y
 CONFIG_SANDBOX_CLK_CCF=y
@@ -116,6 +118,7 @@ CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_SANDBOX=y
+CONFIG_P2SB=y
 CONFIG_PHY=y
 CONFIG_PHY_SANDBOX=y
 CONFIG_PINCTRL=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index c49e05ec319..405b6015474 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -86,6 +86,8 @@ CONFIG_DEBUG_DEVRES=y
 # CONFIG_SPL_SIMPLE_BUS is not set
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
 CONFIG_CLK=y
 CONFIG_CPU=y
 CONFIG_DM_DEMO=y
diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig
index 4808b498502..35f5ca74065 100644
--- a/configs/tools-only_defconfig
+++ b/configs/tools-only_defconfig
@@ -11,6 +11,8 @@ CONFIG_OF_HOSTFILE=y
 CONFIG_DEFAULT_DEVICE_TREE="sandbox"
 CONFIG_IP_DEFRAG=y
 # CONFIG_UDP_FUNCTION_FASTBOOT is not set
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
 CONFIG_SANDBOX_GPIO=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 36f4d1c289d..57f619cca3b 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -56,8 +56,8 @@ static int uclass_add(enum uclass_id id, struct uclass **ucp)
 	*ucp = NULL;
 	uc_drv = lists_uclass_lookup(id);
 	if (!uc_drv) {
-		debug("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
-		      id);
+		printf("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
+		       id);
 		/*
 		 * Use a strange error to make this case easier to find. When
 		 * a uclass is not available it can prevent driver model from
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 840d9fa5e39..363864454bd 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -10,8 +10,10 @@ obj-$(CONFIG_$(SPL_TPL_)CROS_EC_SANDBOX) += cros_ec_sandbox.o
 obj-$(CONFIG_$(SPL_TPL_)CROS_EC_LPC) += cros_ec_lpc.o
 
 ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_SANDBOX) += sandbox_adder.o
 obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
 obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
+obj-$(CONFIG_SANDBOX) += p2sb_sandbox.o p2sb_emul.o
 obj-$(CONFIG_SANDBOX) += swap_case.o
 endif
 
diff --git a/drivers/misc/p2sb_emul.c b/drivers/misc/p2sb_emul.c
new file mode 100644
index 00000000000..c3795c59c08
--- /dev/null
+++ b/drivers/misc/p2sb_emul.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCI emulation device for an x86 Primary-to-Sideband bus
+ *
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_MISC
+#define LOG_DEBUG
+
+#include <common.h>
+#include <axi.h>
+#include <dm.h>
+#include <pci.h>
+#include <asm/test.h>
+#include <p2sb.h>
+
+/**
+ * struct p2sb_emul_platdata - platform data for this device
+ *
+ * @command:	Current PCI command value
+ * @bar:	Current base address values
+ */
+struct p2sb_emul_platdata {
+	u16 command;
+	u32 bar[6];
+};
+
+enum {
+	/* This emulator supports 16 different devices */
+	MEMMAP_SIZE	= 16 << PCR_PORTID_SHIFT,
+};
+
+static struct pci_bar {
+	int type;
+	u32 size;
+} barinfo[] = {
+	{ PCI_BASE_ADDRESS_MEM_TYPE_32, MEMMAP_SIZE },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 },
+};
+
+struct p2sb_emul_priv {
+	u8 regs[16];
+};
+
+static int sandbox_p2sb_emul_read_config(struct udevice *emul, uint offset,
+					 ulong *valuep, enum pci_size_t size)
+{
+	struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
+
+	switch (offset) {
+	case PCI_COMMAND:
+		*valuep = plat->command;
+		break;
+	case PCI_HEADER_TYPE:
+		*valuep = PCI_HEADER_TYPE_NORMAL;
+		break;
+	case PCI_VENDOR_ID:
+		*valuep = SANDBOX_PCI_VENDOR_ID;
+		break;
+	case PCI_DEVICE_ID:
+		*valuep = SANDBOX_PCI_P2SB_EMUL_ID;
+		break;
+	case PCI_CLASS_DEVICE:
+		if (size == PCI_SIZE_8) {
+			*valuep = SANDBOX_PCI_CLASS_SUB_CODE;
+		} else {
+			*valuep = (SANDBOX_PCI_CLASS_CODE << 8) |
+					SANDBOX_PCI_CLASS_SUB_CODE;
+		}
+		break;
+	case PCI_CLASS_CODE:
+		*valuep = SANDBOX_PCI_CLASS_CODE;
+		break;
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_1:
+	case PCI_BASE_ADDRESS_2:
+	case PCI_BASE_ADDRESS_3:
+	case PCI_BASE_ADDRESS_4:
+	case PCI_BASE_ADDRESS_5: {
+		int barnum;
+		u32 *bar;
+
+		barnum = pci_offset_to_barnum(offset);
+		bar = &plat->bar[barnum];
+
+		*valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type,
+					       barinfo[barnum].size);
+		break;
+	}
+	case PCI_CAPABILITY_LIST:
+		*valuep = PCI_CAP_ID_PM_OFFSET;
+		break;
+	}
+
+	return 0;
+}
+
+static int sandbox_p2sb_emul_write_config(struct udevice *emul, uint offset,
+					  ulong value, enum pci_size_t size)
+{
+	struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
+
+	switch (offset) {
+	case PCI_COMMAND:
+		plat->command = value;
+		break;
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_1: {
+		int barnum;
+		u32 *bar;
+
+		barnum = pci_offset_to_barnum(offset);
+		bar = &plat->bar[barnum];
+
+		log_debug("w bar %d=%lx\n", barnum, value);
+		*bar = value;
+		/* space indicator (bit#0) is read-only */
+		*bar |= barinfo[barnum].type;
+		break;
+	}
+	}
+
+	return 0;
+}
+
+static int sandbox_p2sb_emul_find_bar(struct udevice *emul, unsigned int addr,
+				      int *barnump, unsigned int *offsetp)
+{
+	struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
+	int barnum;
+
+	for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) {
+		unsigned int size = barinfo[barnum].size;
+		u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE;
+
+		if (addr >= base && addr < base + size) {
+			*barnump = barnum;
+			*offsetp = addr - base;
+			return 0;
+		}
+	}
+	*barnump = -1;
+
+	return -ENOENT;
+}
+
+static int sandbox_p2sb_emul_read_io(struct udevice *dev, unsigned int addr,
+				     ulong *valuep, enum pci_size_t size)
+{
+	unsigned int offset;
+	int barnum;
+	int ret;
+
+	ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
+	if (ret)
+		return ret;
+
+	if (barnum == 4)
+		*valuep = offset;
+	else if (barnum == 0)
+		*valuep = offset;
+
+	return 0;
+}
+
+static int sandbox_p2sb_emul_write_io(struct udevice *dev, unsigned int addr,
+				      ulong value, enum pci_size_t size)
+{
+	unsigned int offset;
+	int barnum;
+	int ret;
+
+	ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int find_p2sb_channel(struct udevice *emul, uint offset,
+			     struct udevice **devp)
+{
+	uint pid = offset >> PCR_PORTID_SHIFT;
+	struct udevice *p2sb, *dev;
+	int ret;
+
+	ret = sandbox_pci_get_client(emul, &p2sb);
+	if (ret)
+		return log_msg_ret("No client", ret);
+
+	device_foreach_child(dev, p2sb) {
+		struct p2sb_child_platdata *pplat =
+			 dev_get_parent_platdata(dev);
+
+		log_debug("   - child %s, pid %d, want %d\n", dev->name,
+			  pplat->pid, pid);
+		if (pid == pplat->pid) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int sandbox_p2sb_emul_map_physmem(struct udevice *dev,
+					 phys_addr_t addr, unsigned long *lenp,
+					 void **ptrp)
+{
+	struct p2sb_emul_priv *priv = dev_get_priv(dev);
+	struct udevice *child;
+	unsigned int offset;
+	int barnum;
+	int ret;
+
+	log_debug("map %x: ", (uint)addr);
+	ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
+	if (ret)
+		return log_msg_ret("Cannot find bar", ret);
+	log_debug("bar %d, offset %x\n", barnum, offset);
+
+	if (barnum != 0)
+		return log_msg_ret("Unknown BAR", -EINVAL);
+
+	ret = find_p2sb_channel(dev, offset, &child);
+	if (ret)
+		return log_msg_ret("Cannot find channel", ret);
+
+	offset &= ((1 << PCR_PORTID_SHIFT) - 1);
+	ret = axi_read(child, offset, priv->regs, AXI_SIZE_32);
+	if (ret)
+		return log_msg_ret("Child read failed", ret);
+	*ptrp = priv->regs + (offset & 3);
+	*lenp = 4;
+
+	return 0;
+}
+
+static struct dm_pci_emul_ops sandbox_p2sb_emul_emul_ops = {
+	.read_config = sandbox_p2sb_emul_read_config,
+	.write_config = sandbox_p2sb_emul_write_config,
+	.read_io = sandbox_p2sb_emul_read_io,
+	.write_io = sandbox_p2sb_emul_write_io,
+	.map_physmem = sandbox_p2sb_emul_map_physmem,
+};
+
+static const struct udevice_id sandbox_p2sb_emul_ids[] = {
+	{ .compatible = "sandbox,p2sb-emul" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_p2sb_emul_emul) = {
+	.name		= "sandbox_p2sb_emul_emul",
+	.id		= UCLASS_PCI_EMUL,
+	.of_match	= sandbox_p2sb_emul_ids,
+	.ops		= &sandbox_p2sb_emul_emul_ops,
+	.priv_auto_alloc_size = sizeof(struct p2sb_emul_priv),
+	.platdata_auto_alloc_size = sizeof(struct p2sb_emul_platdata),
+};
+
+static struct pci_device_id sandbox_p2sb_emul_supported[] = {
+	{ PCI_VDEVICE(SANDBOX, SANDBOX_PCI_PMC_EMUL_ID) },
+	{},
+};
+
+U_BOOT_PCI_DEVICE(sandbox_p2sb_emul_emul, sandbox_p2sb_emul_supported);
diff --git a/drivers/misc/p2sb_sandbox.c b/drivers/misc/p2sb_sandbox.c
new file mode 100644
index 00000000000..2337df9951d
--- /dev/null
+++ b/drivers/misc/p2sb_sandbox.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sandbox P2SB for testing
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_P2SB
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <p2sb.h>
+
+struct sandbox_p2sb_priv {
+	ulong base;
+};
+
+static int sandbox_p2sb_probe(struct udevice *dev)
+{
+	struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev);
+
+	upriv->mmio_base = dm_pci_read_bar32(dev, 0);
+	printf("mmio base %x\n", upriv->mmio_base);
+
+	return 0;
+}
+
+static struct p2sb_ops sandbox_p2sb_ops = {
+};
+
+static const struct udevice_id sandbox_p2sb_ids[] = {
+	{ .compatible = "sandbox,p2sb" },
+	{ }
+};
+
+U_BOOT_DRIVER(p2sb_sandbox) = {
+	.name = "pmic_pm8916",
+	.id = UCLASS_P2SB,
+	.of_match = sandbox_p2sb_ids,
+	.probe = sandbox_p2sb_probe,
+	.ops = &sandbox_p2sb_ops,
+	.priv_auto_alloc_size = sizeof(struct sandbox_p2sb_priv),
+};
diff --git a/drivers/misc/sandbox_adder.c b/drivers/misc/sandbox_adder.c
new file mode 100644
index 00000000000..df262e62555
--- /dev/null
+++ b/drivers/misc/sandbox_adder.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sandbox adder for p2sb testing
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_MISC
+
+#include <common.h>
+#include <axi.h>
+#include <dm.h>
+#include <misc.h>
+#include <p2sb.h>
+#include <asm/io.h>
+
+struct sandbox_adder_priv {
+	ulong base;
+};
+
+int sandbox_adder_read(struct udevice *dev, ulong address, void *data,
+		       enum axi_size_t size)
+{
+	struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
+	u32 *val = data;
+
+	*val = pplat->pid << 24 | address;
+
+	return 0;
+}
+
+int sandbox_adder_write(struct udevice *dev, ulong address, void *data,
+			enum axi_size_t size)
+{
+	return 0;
+}
+
+static int sandbox_adder_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static struct axi_ops sandbox_adder_ops = {
+	.read	= sandbox_adder_read,
+	.write	= sandbox_adder_write,
+};
+
+static const struct udevice_id sandbox_adder_ids[] = {
+	{ .compatible = "sandbox,adder" },
+	{ }
+};
+
+U_BOOT_DRIVER(adder_sandbox) = {
+	.name = "sandbox_adder",
+	.id = UCLASS_AXI,
+	.of_match = sandbox_adder_ids,
+	.probe = sandbox_adder_probe,
+	.ops = &sandbox_adder_ops,
+	.priv_auto_alloc_size = sizeof(struct sandbox_adder_priv),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 10a19a00c90..129ccb3b496 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -32,6 +32,7 @@ obj-y += ofnode.o
 obj-$(CONFIG_OSD) += osd.o
 obj-$(CONFIG_DM_VIDEO) += panel.o
 obj-$(CONFIG_DM_PCI) += pci.o
+obj-$(CONFIG_P2SB) += p2sb.o
 obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o
 obj-$(CONFIG_PCH) += pch.o
 obj-$(CONFIG_PHY) += phy.o
diff --git a/test/dm/p2sb.c b/test/dm/p2sb.c
new file mode 100644
index 00000000000..ccb75cf3753
--- /dev/null
+++ b/test/dm/p2sb.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for Primary-to-Sideband bus (P2SB)
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <p2sb.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Base test of the PMC uclass */
+static int dm_test_p2sb_base(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	sandbox_set_enable_memio(true);
+	ut_assertok(uclass_get_device_by_name(UCLASS_AXI, "adder", &dev));
+	ut_asserteq(0x03000004, pcr_read32(dev, 4));
+	ut_asserteq(0x300, pcr_read16(dev, 6));
+	ut_asserteq(4, pcr_read8(dev, 4));
+
+	return 0;
+}
+DM_TEST(dm_test_p2sb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 038/108] x86: Move UCLASS_IRQ into a separate file
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (14 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 037/108] sandbox: Add PCI driver and test for p2sb Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04  8:41   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 039/108] sandbox: Add a test for IRQ Simon Glass
                   ` (71 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Update this uclass to support the needs of the apollolake ITSS. It
supports four operations.

Move the uclass into a separate directory so that sandbox can use it too.
Add a new Kconfig to control it and enable this on x86.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add two more operations to IRQ
- Use the IRQ uclass instead of creating a new ITSS uclass

Changes in v2: None

 arch/Kconfig              |  1 +
 arch/x86/cpu/irq.c        |  5 ---
 drivers/misc/Kconfig      |  9 ++++
 drivers/misc/Makefile     |  2 +
 drivers/misc/irq-uclass.c | 53 +++++++++++++++++++++++
 include/irq.h             | 88 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 153 insertions(+), 5 deletions(-)
 create mode 100644 drivers/misc/irq-uclass.c
 create mode 100644 include/irq.h

diff --git a/arch/Kconfig b/arch/Kconfig
index e1f1fcd275b..6865e1f909e 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -186,6 +186,7 @@ config X86
 	imply USB_HOST_ETHER
 	imply PCH
 	imply RTC_MC146818
+	imply IRQ
 
 	# Thing to enable for when SPL/TPL are enabled: SPL
 	imply SPL_DM
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
index 3adc155818c..cb183496b7a 100644
--- a/arch/x86/cpu/irq.c
+++ b/arch/x86/cpu/irq.c
@@ -370,8 +370,3 @@ U_BOOT_DRIVER(irq_router_drv) = {
 	.probe		= irq_router_probe,
 	.priv_auto_alloc_size = sizeof(struct irq_router),
 };
-
-UCLASS_DRIVER(irq) = {
-	.id		= UCLASS_IRQ,
-	.name		= "irq",
-};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1ed2e5d4aa2..7db5c15d999 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -194,6 +194,15 @@ config FSL_SEC_MON
 	  Security Monitor can be transitioned on any security failures,
 	  like software violations or hardware security violations.
 
+config IRQ
+	bool "Intel Interrupt controller"
+	depends on X86 || SANDBOX
+	help
+	  This enabled support for Intel interrupt controllers, including ITSS.
+	  Some devices have extra features, such as apollolake. The
+	  device has its own uclass since there are several operations
+	  involved.
+
 config JZ4780_EFUSE
 	bool "Ingenic JZ4780 eFUSE support"
 	depends on ARCH_JZ47XX
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 363864454bd..9a0c6f08dec 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -41,9 +41,11 @@ obj-$(CONFIG_FS_LOADER) += fs_loader.o
 obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
 obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
 obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
+obj-$(CONFIG_IRQ) += irq-uclass.o
 obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
 obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
 obj-$(CONFIG_IMX8) += imx8/
+obj-$(CONFIG_ITSS) += itss-uclass.o
 obj-$(CONFIG_LED_STATUS) += status_led.o
 obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
 obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
new file mode 100644
index 00000000000..d5182cf1497
--- /dev/null
+++ b/drivers/misc/irq-uclass.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <irq.h>
+
+int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
+{
+	const struct irq_ops *ops = irq_get_ops(dev);
+
+	if (!ops->route_pmc_gpio_gpe)
+		return -ENOSYS;
+
+	return ops->route_pmc_gpio_gpe(dev, pmc_gpe_num);
+}
+
+int irq_set_polarity(struct udevice *dev, uint irq, bool active_low)
+{
+	const struct irq_ops *ops = irq_get_ops(dev);
+
+	if (!ops->set_polarity)
+		return -ENOSYS;
+
+	return ops->set_polarity(dev, irq, active_low);
+}
+
+int irq_snapshot_polarities(struct udevice *dev)
+{
+	const struct irq_ops *ops = irq_get_ops(dev);
+
+	if (!ops->snapshot_polarities)
+		return -ENOSYS;
+
+	return ops->snapshot_polarities(dev);
+}
+
+int irq_restore_polarities(struct udevice *dev)
+{
+	const struct irq_ops *ops = irq_get_ops(dev);
+
+	if (!ops->restore_polarities)
+		return -ENOSYS;
+
+	return ops->restore_polarities(dev);
+}
+
+UCLASS_DRIVER(irq) = {
+	.id		= UCLASS_IRQ,
+	.name		= "irq",
+};
diff --git a/include/irq.h b/include/irq.h
new file mode 100644
index 00000000000..01ded64f160
--- /dev/null
+++ b/include/irq.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IRQ is a type of interrupt controller used on recent Intel SoC.
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __irq_H
+#define __irq_H
+
+/**
+ * struct irq_ops - Operations for the IRQ
+ */
+struct irq_ops {
+	/**
+	 * route_pmc_gpio_gpe() - Get the GPIO for an event
+	 *
+	 * @dev: IRQ device
+	 * @pmc_gpe_num: Event number to check
+	 * @returns GPIO for the event, or -ENOENT if none
+	 */
+	int (*route_pmc_gpio_gpe)(struct udevice *dev, uint pmc_gpe_num);
+
+	/**
+	 * set_polarity() - Set the IRQ polarity
+	 *
+	 * @dev: IRQ device
+	 * @irq: Interrupt number to set
+	 * @active_low: true if active low, false for active high
+	 * @return 0 if OK, -EINVAL if @irq is invalid
+	 */
+	int (*set_polarity)(struct udevice *dev, uint irq, bool active_low);
+
+	/**
+	 * snapshot_polarities() - record IRQ polarities for later restore
+	 *
+	 * @dev: IRQ device
+	 * @return 0
+	 */
+	int (*snapshot_polarities)(struct udevice *dev);
+
+	/**
+	 * restore_polarities() - restore IRQ polarities
+	 *
+	 * @dev: IRQ device
+	 * @return 0
+	 */
+	int (*restore_polarities)(struct udevice *dev);
+};
+
+#define irq_get_ops(dev)	((struct irq_ops *)(dev)->driver->ops)
+
+/**
+ * irq_route_pmc_gpio_gpe() - Get the GPIO for an event
+ *
+ * @dev: IRQ device
+ * @pmc_gpe_num: Event number to check
+ * @returns GPIO for the event, or -ENOENT if none
+ */
+int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num);
+
+/**
+ * irq_set_polarity() - Set the IRQ polarity
+ *
+ * @dev: IRQ device
+ * @irq: Interrupt number to set
+ * @active_low: true if active low, false for active high
+ * @return 0 if OK, -EINVAL if @irq is invalid
+ */
+int irq_set_polarity(struct udevice *dev, uint irq, bool active_low);
+
+/**
+ * irq_snapshot_polarities() - record IRQ polarities for later restore
+ *
+ * @dev: IRQ device
+ * @return 0
+ */
+int irq_snapshot_polarities(struct udevice *dev);
+
+/**
+ * irq_restore_polarities() - restore IRQ polarities
+ *
+ * @dev: IRQ device
+ * @return 0
+ */
+int irq_restore_polarities(struct udevice *dev);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 039/108] sandbox: Add a test for IRQ
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (15 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 038/108] x86: Move UCLASS_IRQ into a separate file Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04  8:45   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 040/108] x86: Define the SPL image start Simon Glass
                   ` (70 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add a simple sandbox test for this uclass.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Change the sandbox test from ITSS to IRQ

Changes in v2: None

 arch/sandbox/dts/test.dts          |  4 +++
 configs/sandbox_defconfig          |  3 +-
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig      |  1 +
 drivers/misc/Makefile              |  2 +-
 drivers/misc/irq_sandbox.c         | 55 ++++++++++++++++++++++++++++++
 test/dm/Makefile                   |  1 +
 test/dm/irq.c                      | 32 +++++++++++++++++
 8 files changed, 97 insertions(+), 2 deletions(-)
 create mode 100644 drivers/misc/irq_sandbox.c
 create mode 100644 test/dm/irq.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 24631770544..05f26df6a82 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -349,6 +349,10 @@
 		vss-microvolts = <0>;
 	};
 
+	irq {
+		compatible = "sandbox,irq";
+	};
+
 	lcd {
 		u-boot,dm-pre-reloc;
 		compatible = "sandbox,lcd-sdl";
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f8b78b8d7e1..fd2cd764e2c 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -130,6 +130,8 @@ CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
 CONFIG_CROS_EC_SANDBOX=y
 CONFIG_CROS_EC_SPI=y
+CONFIG_IRQ=y
+CONFIG_P2SB=y
 CONFIG_PWRSEQ=y
 CONFIG_SPL_PWRSEQ=y
 CONFIG_I2C_EEPROM=y
@@ -150,7 +152,6 @@ CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_SANDBOX=y
-CONFIG_P2SB=y
 CONFIG_PHY=y
 CONFIG_PHY_SANDBOX=y
 CONFIG_PINCTRL=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 230d65b14a7..d1c18ff96cd 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -98,6 +98,7 @@ CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
 CONFIG_CROS_EC_SANDBOX=y
 CONFIG_CROS_EC_SPI=y
+CONFIG_IRQ=y
 CONFIG_PWRSEQ=y
 CONFIG_SPL_PWRSEQ=y
 CONFIG_I2C_EEPROM=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 405b6015474..0f66b2aee0a 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -118,6 +118,7 @@ CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
 CONFIG_CROS_EC_SANDBOX=y
 CONFIG_CROS_EC_SPI=y
+CONFIG_IRQ=y
 CONFIG_PWRSEQ=y
 CONFIG_SPL_PWRSEQ=y
 CONFIG_MMC_SANDBOX=y
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 9a0c6f08dec..bd2469f67b0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -42,10 +42,10 @@ obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
 obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
 obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
 obj-$(CONFIG_IRQ) += irq-uclass.o
+obj-$(CONFIG_SANDBOX) += irq_sandbox.o
 obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
 obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
 obj-$(CONFIG_IMX8) += imx8/
-obj-$(CONFIG_ITSS) += itss-uclass.o
 obj-$(CONFIG_LED_STATUS) += status_led.o
 obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
 obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
diff --git a/drivers/misc/irq_sandbox.c b/drivers/misc/irq_sandbox.c
new file mode 100644
index 00000000000..6dda1a4c442
--- /dev/null
+++ b/drivers/misc/irq_sandbox.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sandbox driver for interrupts
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <irq.h>
+
+static int sandbox_set_polarity(struct udevice *dev, uint irq, bool active_low)
+{
+	if (irq > 10)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sandbox_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
+{
+	if (pmc_gpe_num > 10)
+		return -ENOENT;
+
+	return pmc_gpe_num + 1;
+}
+
+static int sandbox_snapshot_polarities(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sandbox_restore_polarities(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct irq_ops sandbox_irq_ops = {
+	.route_pmc_gpio_gpe	= sandbox_route_pmc_gpio_gpe,
+	.set_polarity		= sandbox_set_polarity,
+	.snapshot_polarities	= sandbox_snapshot_polarities,
+	.restore_polarities	= sandbox_restore_polarities,
+};
+
+static const struct udevice_id sandbox_irq_ids[] = {
+	{ .compatible = "sandbox,irq"},
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_irq_drv) = {
+	.name		= "sandbox_irq",
+	.id		= UCLASS_IRQ,
+	.of_match	= sandbox_irq_ids,
+	.ops		= &sandbox_irq_ops,
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 129ccb3b496..a2687831696 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_SOUND) += i2s.o
+obj-y += irq.o
 obj-$(CONFIG_LED) += led.o
 obj-$(CONFIG_DM_MAILBOX) += mailbox.o
 obj-$(CONFIG_DM_MMC) += mmc.o
diff --git a/test/dm/irq.c b/test/dm/irq.c
new file mode 100644
index 00000000000..726189c59f7
--- /dev/null
+++ b/test/dm/irq.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for irq uclass
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <irq.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Base test of the irq uclass */
+static int dm_test_irq_base(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_IRQ, &dev));
+
+	ut_asserteq(5, irq_route_pmc_gpio_gpe(dev, 4));
+	ut_asserteq(-ENOENT, irq_route_pmc_gpio_gpe(dev, 14));
+
+	ut_assertok(irq_set_polarity(dev, 4, true));
+	ut_asserteq(-EINVAL, irq_set_polarity(dev, 14, true));
+
+	ut_assertok(irq_snapshot_polarities(dev));
+	ut_assertok(irq_restore_polarities(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_irq_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 040/108] x86: Define the SPL image start
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (16 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 039/108] sandbox: Add a test for IRQ Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04  8:46   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 041/108] x86: Reduce mrccache record alignment size Simon Glass
                   ` (69 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Define this symbol so that we can use binman symbols correctly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/u-boot-spl.lds | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds
index c1e9bfbf66f..e6c22895b35 100644
--- a/arch/x86/cpu/u-boot-spl.lds
+++ b/arch/x86/cpu/u-boot-spl.lds
@@ -17,7 +17,10 @@ SECTIONS
 
 	. = IMAGE_TEXT_BASE;	/* Location of bootcode in flash */
 	__text_start = .;
-	.text  : { *(.text*); }
+	.text  : {
+		__image_copy_start = .;
+		*(.text*);
+	}
 
 	. = ALIGN(4);
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 041/108] x86: Reduce mrccache record alignment size
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (17 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 040/108] x86: Define the SPL image start Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04  8:50   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 042/108] x86: Correct mrccache find_next_mrc_cache() calculation Simon Glass
                   ` (68 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present the records are 4KB in size. This is unnecessarily large when
the SPI-flash erase size is 256 bytes. Reduce it so it will be more
efficient with Apollolake's 24-byte variable-data record.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/mrccache.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h
index 40fda856ff4..abf58182237 100644
--- a/arch/x86/include/asm/mrccache.h
+++ b/arch/x86/include/asm/mrccache.h
@@ -7,7 +7,7 @@
 #ifndef _ASM_MRCCACHE_H
 #define _ASM_MRCCACHE_H
 
-#define MRC_DATA_ALIGN		0x1000
+#define MRC_DATA_ALIGN		0x100
 #define MRC_DATA_SIGNATURE	(('M' << 0) | ('R' << 8) | \
 				 ('C' << 16) | ('D'<<24))
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 042/108] x86: Correct mrccache find_next_mrc_cache() calculation
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (18 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 041/108] x86: Reduce mrccache record alignment size Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04 15:01   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree Simon Glass
                   ` (67 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

This should take account of the end of the new cache record since a record
cannot extend beyond the end of the flash region. This problem was not
seen before due to the alignment of the relatively small amount of MRC
data.

But with apollolake the MRC data is about 45KB, even if most of it is
zeroes.

Fix this bug and update the parameter name to be less confusing.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add an extra size parameter to the find_next_mrc_cache() function

Changes in v2: None

 arch/x86/lib/mrccache.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index 33bb52039bd..7292d1fe070 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -80,21 +80,26 @@ struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
 /**
  * find_next_mrc_cache() - get next cache entry
  *
+ * This moves to the next cache entry in the region, making sure it has enough
+ * space to hold data of size @data_size.
+ *
  * @entry:	MRC cache flash area
  * @cache:	Entry to start from
+ * @data_size:	Required data size of the new entry
  *
  * @return next cache entry if found, NULL if we got to the end
  */
 static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
-		struct mrc_data_container *cache)
+		struct mrc_data_container *prev, int data_size)
 {
+	struct mrc_data_container *cache;
 	ulong base_addr, end_addr;
 
 	base_addr = entry->base + entry->offset;
 	end_addr = base_addr + entry->length;
 
-	cache = next_mrc_block(cache);
-	if ((ulong)cache >= end_addr) {
+	cache = next_mrc_block(prev);
+	if ((ulong)cache + mrc_block_size(prev->data_size) > end_addr) {
 		/* Crossed the boundary */
 		cache = NULL;
 		debug("%s: no available entries found\n", __func__);
@@ -131,7 +136,7 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
 
 	/* Move to the next block, which will be the first unused block */
 	if (cache)
-		cache = find_next_mrc_cache(entry, cache);
+		cache = find_next_mrc_cache(entry, cache, cur->data_size);
 
 	/*
 	 * If we have got to the end, erase the entire mrc-cache area and start
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (19 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 042/108] x86: Correct mrccache find_next_mrc_cache() calculation Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04 15:06   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 044/108] x86: Adjust mrccache_get_region() to support get_mmap() Simon Glass
                   ` (66 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Change the algorithm to first find the flash device then read the
properties using the livetree API. With this change the device is not
probed so this needs to be done in mrccache_save().

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Update mrccache livetree patch to just convert to livetree

Changes in v2: None

 arch/x86/lib/mrccache.c | 55 +++++++++++++++++++----------------------
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index 7292d1fe070..b8bc5de602c 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -14,6 +14,8 @@
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/mrccache.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -201,45 +203,37 @@ int mrccache_reserve(void)
 
 int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
 {
-	const void *blob = gd->fdt_blob;
-	int node, mrc_node;
+	struct udevice *dev;
+	ofnode mrc_node;
 	u32 reg[2];
 	int ret;
 
-	/* Find the flash chip within the SPI controller node */
-	node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
-	if (node < 0) {
-		debug("%s: Cannot find SPI flash\n", __func__);
-		return -ENOENT;
-	}
-
-	if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) {
-		debug("%s: Cannot find memory map\n", __func__);
-		return -EINVAL;
-	}
+	/*
+	 * Find the flash chip within the SPI controller node. Avoid probing
+	 * the device here since it may put it into a strange state where the
+	 * memory map cannot be read.
+	 */
+	ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
+	if (ret)
+		return log_msg_ret("Cannot find SPI flash\n", ret);
+	ret = dev_read_u32_array(dev, "memory-map", reg, 2);
+	if (ret)
+		return log_msg_ret("Cannot find memory map\n", ret);
 	entry->base = reg[0];
 
 	/* Find the place where we put the MRC cache */
-	mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
-	if (mrc_node < 0) {
-		debug("%s: Cannot find node\n", __func__);
-		return -EPERM;
-	}
+	mrc_node = dev_read_subnode(dev, "rw-mrc-cache");
+	if (!ofnode_valid(mrc_node))
+		return log_msg_ret("Cannot find node", -EPERM);
 
-	if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) {
-		debug("%s: Cannot find address\n", __func__);
-		return -EINVAL;
-	}
+	ret = ofnode_read_u32_array(mrc_node, "reg", reg, 2);
+	if (ret)
+		return log_msg_ret("Cannot find address", ret);
 	entry->offset = reg[0];
 	entry->length = reg[1];
 
-	if (devp) {
-		ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
-						     devp);
-		debug("ret = %d\n", ret);
-		if (ret)
-			return ret;
-	}
+	if (devp)
+		*devp = dev;
 
 	return 0;
 }
@@ -257,6 +251,9 @@ int mrccache_save(void)
 	      gd->arch.mrc_output_len);
 
 	ret = mrccache_get_region(&sf, &entry);
+	if (ret)
+		goto err_entry;
+	ret = device_probe(sf);
 	if (ret)
 		goto err_entry;
 	data  = (struct mrc_data_container *)gd->arch.mrc_output;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 044/108] x86: Adjust mrccache_get_region() to support get_mmap()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (20 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 045/108] x86: Add a new global_data member for the cache record Simon Glass
                   ` (65 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

It is now possible to obtain the memory map for a SPI controllers instead
of having it hard-coded in the device tree. Update the code to support
this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2:
- Use SPI mmap() instead of SPI flash

 arch/x86/lib/mrccache.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index b8bc5de602c..b5d1ea11c5b 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -205,6 +205,9 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
 {
 	struct udevice *dev;
 	ofnode mrc_node;
+	ulong map_base;
+	uint map_size;
+	uint offset;
 	u32 reg[2];
 	int ret;
 
@@ -216,10 +219,15 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
 	ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
 	if (ret)
 		return log_msg_ret("Cannot find SPI flash\n", ret);
-	ret = dev_read_u32_array(dev, "memory-map", reg, 2);
-	if (ret)
-		return log_msg_ret("Cannot find memory map\n", ret);
-	entry->base = reg[0];
+	ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
+	if (!ret) {
+		entry->base = map_base;
+	} else {
+		ret = dev_read_u32_array(dev, "memory-map", reg, 2);
+		if (ret)
+			return log_msg_ret("Cannot find memory map\n", ret);
+		entry->base = reg[0];
+	}
 
 	/* Find the place where we put the MRC cache */
 	mrc_node = dev_read_subnode(dev, "rw-mrc-cache");
@@ -234,6 +242,8 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
 
 	if (devp)
 		*devp = dev;
+	debug("MRC cache in '%s', offset %x, len %x, base %x\n",
+	      dev->name, entry->offset, entry->length, entry->base);
 
 	return 0;
 }
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 045/108] x86: Add a new global_data member for the cache record
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (21 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 044/108] x86: Adjust mrccache_get_region() to support get_mmap() Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 046/108] x86: Tidy up error handling in mrccache_save() Simon Glass
                   ` (64 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present we reuse the mrc_output char * to also point to the cache
record after it has been set up. This is confusing and doesn't save much
data space.

Add a new mrc_cache member instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/global_data.h |  2 ++
 arch/x86/lib/mrccache.c            | 11 +++++------
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 7f3ada06f61..67d9a38177e 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -10,6 +10,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/processor.h>
+#include <asm/mrccache.h>
 
 enum pei_boot_mode_t {
 	PEI_BOOT_NONE = 0,
@@ -93,6 +94,7 @@ struct arch_global_data {
 	/* MRC training data to save for the next boot */
 	char *mrc_output;
 	unsigned int mrc_output_len;
+	struct mrc_data_container *mrc_cache;
 	ulong table;			/* Table pointer from previous loader */
 	int turbo_state;		/* Current turbo state */
 	struct irq_routing_table *pirq_routing_table;
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index b5d1ea11c5b..d1334a4542d 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -183,8 +183,7 @@ static void mrccache_setup(void *data)
 	cache->reserved = 0;
 	memcpy(cache->data, gd->arch.mrc_output, cache->data_size);
 
-	/* gd->arch.mrc_output now points to the container */
-	gd->arch.mrc_output = (char *)cache;
+	gd->arch.mrc_cache = cache;
 }
 
 int mrccache_reserve(void)
@@ -250,7 +249,7 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
 
 int mrccache_save(void)
 {
-	struct mrc_data_container *data;
+	struct mrc_data_container *cache;
 	struct mrc_region entry;
 	struct udevice *sf;
 	int ret;
@@ -266,10 +265,10 @@ int mrccache_save(void)
 	ret = device_probe(sf);
 	if (ret)
 		goto err_entry;
-	data  = (struct mrc_data_container *)gd->arch.mrc_output;
-	ret = mrccache_update(sf, &entry, data);
+	cache = gd->arch.mrc_cache;
+	ret = mrccache_update(sf, &entry, cache);
 	if (!ret) {
-		debug("Saved MRC data with checksum %04x\n", data->checksum);
+		debug("Saved MRC data with checksum %04x\n", cache->checksum);
 	} else if (ret == -EEXIST) {
 		debug("MRC data is the same as last time, skipping save\n");
 		ret = 0;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 046/108] x86: Tidy up error handling in mrccache_save()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (22 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 045/108] x86: Add a new global_data member for the cache record Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 047/108] x86: Update mrccache to support multiple caches Simon Glass
                   ` (63 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

This function is a bit confusing at present due to the error handling.
Update it to remove the goto, returning errors as they happen.

While we are here, use hex for the data size since this is the norm in
U-Boot.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3:
- Move an additional error handling fix from a future patch

Changes in v2: None

 arch/x86/lib/mrccache.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index d1334a4542d..b97bb9b5998 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -163,7 +163,7 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
 				 cur);
 	if (ret) {
 		debug("Failed to write to SPI flash\n");
-		return ret;
+		return log_msg_ret("Cannot update mrccache", ret);
 	}
 
 	return 0;
@@ -256,28 +256,23 @@ int mrccache_save(void)
 
 	if (!gd->arch.mrc_output_len)
 		return 0;
-	debug("Saving %d bytes of MRC output data to SPI flash\n",
+	debug("Saving %#x bytes of MRC output data to SPI flash\n",
 	      gd->arch.mrc_output_len);
 
 	ret = mrccache_get_region(&sf, &entry);
 	if (ret)
-		goto err_entry;
+		return log_msg_ret("Cannot get region", ret);
 	ret = device_probe(sf);
 	if (ret)
-		goto err_entry;
+		return log_msg_ret("Cannot probe device", ret);
 	cache = gd->arch.mrc_cache;
 	ret = mrccache_update(sf, &entry, cache);
-	if (!ret) {
+	if (!ret)
 		debug("Saved MRC data with checksum %04x\n", cache->checksum);
-	} else if (ret == -EEXIST) {
+	else if (ret == -EEXIST)
 		debug("MRC data is the same as last time, skipping save\n");
-		ret = 0;
-	}
 
-err_entry:
-	if (ret)
-		debug("%s: Failed: %d\n", __func__, ret);
-	return ret;
+	return 0;
 }
 
 int mrccache_spl_save(void)
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 047/108] x86: Update mrccache to support multiple caches
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (23 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 046/108] x86: Tidy up error handling in mrccache_save() Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04 15:22   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 048/108] x86: Add mrccache support for a 'variable' cache Simon Glass
                   ` (62 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

With apollolake we need to support a normal cache, which almost never
changes and a much smaller 'variable' cache which changes every time.

Update the code to add a cache type, use an array for the caches and use a
for loop to iterate over the caches.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Move line related to variable-cache into the next patch

Changes in v2: None

 arch/x86/cpu/broadwell/sdram.c     |  8 ++-
 arch/x86/cpu/ivybridge/sdram.c     |  8 ++-
 arch/x86/cpu/quark/dram.c          |  8 ++-
 arch/x86/include/asm/global_data.h | 21 +++++--
 arch/x86/include/asm/mrccache.h    | 11 +++-
 arch/x86/lib/fsp/fsp_common.c      |  2 +-
 arch/x86/lib/fsp1/fsp_dram.c       |  8 ++-
 arch/x86/lib/mrccache.c            | 88 ++++++++++++++++++++----------
 8 files changed, 106 insertions(+), 48 deletions(-)

diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c
index b31d78c092a..107c04691b0 100644
--- a/arch/x86/cpu/broadwell/sdram.c
+++ b/arch/x86/cpu/broadwell/sdram.c
@@ -82,7 +82,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
 	struct mrc_region entry;
 	int ret;
 
-	ret = mrccache_get_region(NULL, &entry);
+	ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
 	if (ret)
 		return ret;
 	mrc_cache = mrccache_find_current(&entry);
@@ -168,12 +168,14 @@ int dram_init(void)
 	      pei_data->data_to_save);
 	/* S3 resume: don't save scrambler seed or MRC data */
 	if (pei_data->boot_mode != SLEEP_STATE_S3) {
+		struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
+
 		/*
 		 * This will be copied to SDRAM in reserve_arch(), then written
 		 * to SPI flash in mrccache_save()
 		 */
-		gd->arch.mrc_output = (char *)pei_data->data_to_save;
-		gd->arch.mrc_output_len = pei_data->data_to_save_size;
+		mrc->buf = (char *)pei_data->data_to_save;
+		mrc->len = pei_data->data_to_save_size;
 	}
 	gd->arch.pei_meminfo = pei_data->meminfo;
 
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index 8a58d0383d5..8b03406666e 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -115,7 +115,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
 	ret = read_seed_from_cmos(pei_data);
 	if (ret)
 		return ret;
-	ret = mrccache_get_region(NULL, &entry);
+	ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
 	if (ret)
 		return ret;
 	mrc_cache = mrccache_find_current(&entry);
@@ -537,12 +537,14 @@ int dram_init(void)
 
 	/* S3 resume: don't save scrambler seed or MRC data */
 	if (pei_data->boot_mode != PEI_BOOT_RESUME) {
+		struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
+
 		/*
 		 * This will be copied to SDRAM in reserve_arch(), then written
 		 * to SPI flash in mrccache_save()
 		 */
-		gd->arch.mrc_output = (char *)pei_data->mrc_output;
-		gd->arch.mrc_output_len = pei_data->mrc_output_len;
+		mrc->buf = (char *)pei_data->mrc_output;
+		mrc->len = pei_data->mrc_output_len;
 		ret = write_seeds_to_cmos(pei_data);
 		if (ret)
 			debug("Failed to write seeds to CMOS: %d\n", ret);
diff --git a/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c
index 51f9659ab15..3994355112b 100644
--- a/arch/x86/cpu/quark/dram.c
+++ b/arch/x86/cpu/quark/dram.c
@@ -22,7 +22,7 @@ static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params)
 	struct mrc_region entry;
 	int ret;
 
-	ret = mrccache_get_region(NULL, &entry);
+	ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
 	if (ret)
 		return ret;
 
@@ -152,9 +152,11 @@ int dram_init(void)
 #ifdef CONFIG_ENABLE_MRC_CACHE
 	cache = malloc(sizeof(struct mrc_timings));
 	if (cache) {
+		struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
+
 		memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings));
-		gd->arch.mrc_output = cache;
-		gd->arch.mrc_output_len = sizeof(struct mrc_timings);
+		mrc->buf = cache;
+		mrc->len = sizeof(struct mrc_timings);
 	}
 #endif
 
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 67d9a38177e..6d21ddc0d1e 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -67,6 +67,21 @@ struct mtrr_request {
 	uint64_t size;
 };
 
+/**
+ * struct mrc_output - holds the MRC data
+ *
+ * @buf: MRC training data to save for the next boot. This is set to point to
+ *	the raw data after SDRAM init is complete. Then mrccache_setup()
+ *	turns it into a proper cache record with a checksum
+ * @len: Length of @buf
+ * @cache: Resulting cache record
+ */
+struct mrc_output {
+	char *buf;
+	uint len;
+	struct mrc_data_container *cache;
+};
+
 /* Architecture-specific global data */
 struct arch_global_data {
 	u64 gdt[X86_GDT_NUM_ENTRIES] __aligned(16);
@@ -91,10 +106,8 @@ struct arch_global_data {
 	struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
 	int mtrr_req_count;
 	int has_mtrr;
-	/* MRC training data to save for the next boot */
-	char *mrc_output;
-	unsigned int mrc_output_len;
-	struct mrc_data_container *mrc_cache;
+	/* MRC training data */
+	struct mrc_output mrc[MRC_TYPE_COUNT];
 	ulong table;			/* Table pointer from previous loader */
 	int turbo_state;		/* Current turbo state */
 	struct irq_routing_table *pirq_routing_table;
diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h
index abf58182237..b81e2b2fb6a 100644
--- a/arch/x86/include/asm/mrccache.h
+++ b/arch/x86/include/asm/mrccache.h
@@ -27,6 +27,13 @@ struct mrc_region {
 	u32	length;
 };
 
+/* Types of MRC data */
+enum mrc_type_t {
+	MRC_TYPE_NORMAL,
+
+	MRC_TYPE_COUNT,
+};
+
 struct udevice;
 
 /**
@@ -84,6 +91,7 @@ int mrccache_reserve(void);
  *   triggers PCI bus enumeration during which insufficient memory issue
  *   might be exposed and it causes subsequent SPI flash probe fails).
  *
+ * @type:	Type of MRC data to use
  * @devp:	Returns pointer to the SPI flash device
  * @entry:	Position and size of MRC cache in SPI flash
  * @return 0 if success, -ENOENT if SPI flash node does not exist in the
@@ -91,7 +99,8 @@ int mrccache_reserve(void);
  * tree, -EINVAL if MRC region properties format is incorrect, other error
  * if SPI flash probe failed.
  */
-int mrccache_get_region(struct udevice **devp, struct mrc_region *entry);
+int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
+			struct mrc_region *entry);
 
 /**
  * mrccache_save() - save MRC data to the SPI flash
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
index 40ba866d77c..c1c30ce0eb6 100644
--- a/arch/x86/lib/fsp/fsp_common.c
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -63,7 +63,7 @@ void *fsp_prepare_mrc_cache(void)
 	struct mrc_region entry;
 	int ret;
 
-	ret = mrccache_get_region(NULL, &entry);
+	ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
 	if (ret)
 		return NULL;
 
diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c
index 6a3349b42af..5ef89744b94 100644
--- a/arch/x86/lib/fsp1/fsp_dram.c
+++ b/arch/x86/lib/fsp1/fsp_dram.c
@@ -15,9 +15,11 @@ int dram_init(void)
 	if (ret)
 		return ret;
 
-	if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
-		gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
-					       &gd->arch.mrc_output_len);
+	if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
+		struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
+
+		mrc->buf = fsp_get_nvs_data(gd->arch.hob_list, &mrc->len);
+	}
 
 	return 0;
 }
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index b97bb9b5998..36444048c6c 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -169,38 +169,45 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
 	return 0;
 }
 
-static void mrccache_setup(void *data)
+static void mrccache_setup(struct mrc_output *mrc, void *data)
 {
 	struct mrc_data_container *cache = data;
 	u16 checksum;
 
 	cache->signature = MRC_DATA_SIGNATURE;
-	cache->data_size = gd->arch.mrc_output_len;
-	checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
+	cache->data_size = mrc->len;
+	checksum = compute_ip_checksum(mrc->buf, cache->data_size);
 	debug("Saving %d bytes for MRC output data, checksum %04x\n",
 	      cache->data_size, checksum);
 	cache->checksum = checksum;
 	cache->reserved = 0;
-	memcpy(cache->data, gd->arch.mrc_output, cache->data_size);
+	memcpy(cache->data, mrc->buf, cache->data_size);
 
-	gd->arch.mrc_cache = cache;
+	mrc->cache = cache;
 }
 
 int mrccache_reserve(void)
 {
-	if (!gd->arch.mrc_output_len)
-		return 0;
+	int i;
+
+	for (i = 0; i < MRC_TYPE_COUNT; i++) {
+		struct mrc_output *mrc = &gd->arch.mrc[i];
 
-	/* adjust stack pointer to store pure cache data plus the header */
-	gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
-	mrccache_setup((void *)gd->start_addr_sp);
+		if (!mrc->len)
+			continue;
 
-	gd->start_addr_sp &= ~0xf;
+		/* adjust stack pointer to store pure cache data plus header */
+		gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE);
+		mrccache_setup(mrc, (void *)gd->start_addr_sp);
+
+		gd->start_addr_sp &= ~0xf;
+	}
 
 	return 0;
 }
 
-int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
+int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
+			struct mrc_region *entry)
 {
 	struct udevice *dev;
 	ofnode mrc_node;
@@ -241,31 +248,33 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
 
 	if (devp)
 		*devp = dev;
-	debug("MRC cache in '%s', offset %x, len %x, base %x\n",
-	      dev->name, entry->offset, entry->length, entry->base);
+	debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
+	      type, dev->name, entry->offset, entry->length, entry->base);
 
 	return 0;
 }
 
-int mrccache_save(void)
+static int mrccache_save_type(enum mrc_type_t type)
 {
 	struct mrc_data_container *cache;
+	struct mrc_output *mrc;
 	struct mrc_region entry;
 	struct udevice *sf;
 	int ret;
 
-	if (!gd->arch.mrc_output_len)
+	mrc = &gd->arch.mrc[type];
+	if (!mrc->len)
 		return 0;
-	debug("Saving %#x bytes of MRC output data to SPI flash\n",
-	      gd->arch.mrc_output_len);
-
-	ret = mrccache_get_region(&sf, &entry);
+	log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n",
+		  mrc->len, type);
+	ret = mrccache_get_region(type, &sf, &entry);
 	if (ret)
 		return log_msg_ret("Cannot get region", ret);
 	ret = device_probe(sf);
 	if (ret)
 		return log_msg_ret("Cannot probe device", ret);
-	cache = gd->arch.mrc_cache;
+	cache = mrc->cache;
+
 	ret = mrccache_update(sf, &entry, cache);
 	if (!ret)
 		debug("Saved MRC data with checksum %04x\n", cache->checksum);
@@ -275,17 +284,36 @@ int mrccache_save(void)
 	return 0;
 }
 
+int mrccache_save(void)
+{
+	int i;
+
+	for (i = 0; i < MRC_TYPE_COUNT; i++) {
+		int ret;
+
+		ret = mrccache_save_type(i);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int mrccache_spl_save(void)
 {
-	void *data;
-	int size;
-
-	size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE;
-	data = malloc(size);
-	if (!data)
-		return log_msg_ret("Allocate MRC cache block", -ENOMEM);
-	mrccache_setup(data);
-	gd->arch.mrc_output = data;
+	int i;
+
+	for (i = 0; i < MRC_TYPE_COUNT; i++) {
+		struct mrc_output *mrc = &gd->arch.mrc[i];
+		void *data;
+		int size;
+
+		size = mrc->len + MRC_DATA_HEADER_SIZE;
+		data = malloc(size);
+		if (!data)
+			return log_msg_ret("Allocate MRC cache block", -ENOMEM);
+		mrccache_setup(mrc, data);
+	}
 
 	return mrccache_save();
 }
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 048/108] x86: Add mrccache support for a 'variable' cache
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (24 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 047/108] x86: Update mrccache to support multiple caches Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04 15:23   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 049/108] x86: Move fsp_prepare_mrc_cache() to fsp1 directory Simon Glass
                   ` (61 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add support for a second cache type, for apollolake.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Move the mrccache_get_region() change into this patch

Changes in v2: None

 arch/x86/include/asm/mrccache.h | 1 +
 arch/x86/lib/mrccache.c         | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h
index b81e2b2fb6a..0917cf24704 100644
--- a/arch/x86/include/asm/mrccache.h
+++ b/arch/x86/include/asm/mrccache.h
@@ -30,6 +30,7 @@ struct mrc_region {
 /* Types of MRC data */
 enum mrc_type_t {
 	MRC_TYPE_NORMAL,
+	MRC_TYPE_VAR,
 
 	MRC_TYPE_COUNT,
 };
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index 36444048c6c..2972f270811 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -236,7 +236,8 @@ int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
 	}
 
 	/* Find the place where we put the MRC cache */
-	mrc_node = dev_read_subnode(dev, "rw-mrc-cache");
+	mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
+				    "rw-mrc-cache" : "rw-var-mrc-cache");
 	if (!ofnode_valid(mrc_node))
 		return log_msg_ret("Cannot find node", -EPERM);
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 049/108] x86: Move fsp_prepare_mrc_cache() to fsp1 directory
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (25 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 048/108] x86: Add mrccache support for a 'variable' cache Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 050/108] x86: Set the DRAM banks to reflect real location Simon Glass
                   ` (60 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

This function needs to be different for FSP2, so move the existing
function into the fsp1 directory. Since it is only called from one file,
drop it from the header file.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/fsp/fsp_support.h |  7 -------
 arch/x86/lib/fsp/fsp_common.c          | 20 --------------------
 arch/x86/lib/fsp1/fsp_common.c         | 20 ++++++++++++++++++++
 3 files changed, 20 insertions(+), 27 deletions(-)

diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h
index 4ac27d26f55..29e511415cd 100644
--- a/arch/x86/include/asm/fsp/fsp_support.h
+++ b/arch/x86/include/asm/fsp/fsp_support.h
@@ -143,13 +143,6 @@ int fsp_init_phase_pci(void);
  */
 int fsp_scan_for_ram_size(void);
 
-/**
- * fsp_prepare_mrc_cache() - Find the DRAM training data from the MRC cache
- *
- * @return pointer to data, or NULL if no cache or no data found in the cache
- */
-void *fsp_prepare_mrc_cache(void);
-
 /**
  * fsp_notify() - FSP notification wrapper function
  *
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
index c1c30ce0eb6..6b7a614e929 100644
--- a/arch/x86/lib/fsp/fsp_common.c
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -57,26 +57,6 @@ void board_final_cleanup(void)
 		debug("OK\n");
 }
 
-void *fsp_prepare_mrc_cache(void)
-{
-	struct mrc_data_container *cache;
-	struct mrc_region entry;
-	int ret;
-
-	ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
-	if (ret)
-		return NULL;
-
-	cache = mrccache_find_current(&entry);
-	if (!cache)
-		return NULL;
-
-	debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
-	      cache->data, cache->data_size, cache->checksum);
-
-	return cache->data;
-}
-
 #ifdef CONFIG_HAVE_ACPI_RESUME
 int fsp_save_s3_stack(void)
 {
diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c
index e8066d8de39..ec9c218778d 100644
--- a/arch/x86/lib/fsp1/fsp_common.c
+++ b/arch/x86/lib/fsp1/fsp_common.c
@@ -18,6 +18,26 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static void *fsp_prepare_mrc_cache(void)
+{
+	struct mrc_data_container *cache;
+	struct mrc_region entry;
+	int ret;
+
+	ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
+	if (ret)
+		return NULL;
+
+	cache = mrccache_find_current(&entry);
+	if (!cache)
+		return NULL;
+
+	debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
+	      cache->data, cache->data_size, cache->checksum);
+
+	return cache->data;
+}
+
 int arch_fsp_init(void)
 {
 	void *nvs;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 050/108] x86: Set the DRAM banks to reflect real location
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (26 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 049/108] x86: Move fsp_prepare_mrc_cache() to fsp1 directory Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-04 15:24   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 051/108] x86: Set up the MTRR for SDRAM Simon Glass
                   ` (59 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present with fsp a single DRAM bank is added which extends to the
whole size of memory. However there is typically only 2GB of memory
available below the 4GB boundary, and this is what is used by U-Boot while
running in 32-bit mode.

Scan the tables to set the banks correct. The first bank is set to memory
below 4GB, and the rest of memory is put into subsequent banks.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Move mtrr_add_request() call to next patch

Changes in v2: None

 arch/x86/lib/fsp/fsp_dram.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c
index 2d1023068fe..3ede9b73fe2 100644
--- a/arch/x86/lib/fsp/fsp_dram.c
+++ b/arch/x86/lib/fsp/fsp_dram.c
@@ -37,8 +37,36 @@ int fsp_scan_for_ram_size(void)
 
 int dram_init_banksize(void)
 {
+	const struct hob_header *hdr;
+	struct hob_res_desc *res_desc;
+	phys_addr_t low_end;
+	uint bank;
+
+	low_end = 0;
+	for (bank = 1, hdr = gd->arch.hob_list;
+	     bank < CONFIG_NR_DRAM_BANKS && !end_of_hob(hdr);
+	     hdr = get_next_hob(hdr)) {
+		if (hdr->type != HOB_TYPE_RES_DESC)
+			continue;
+		res_desc = (struct hob_res_desc *)hdr;
+		if (res_desc->type != RES_SYS_MEM &&
+		    res_desc->type != RES_MEM_RESERVED)
+			continue;
+		if (res_desc->phys_start < (1ULL << 32)) {
+			low_end = max(low_end,
+				      res_desc->phys_start + res_desc->len);
+			continue;
+		}
+
+		gd->bd->bi_dram[bank].start = res_desc->phys_start;
+		gd->bd->bi_dram[bank].size = res_desc->len;
+		log_debug("ram %llx %llx\n", gd->bd->bi_dram[bank].start,
+			  gd->bd->bi_dram[bank].size);
+	}
+
+	/* Add the memory below 4GB */
 	gd->bd->bi_dram[0].start = 0;
-	gd->bd->bi_dram[0].size = gd->ram_size;
+	gd->bd->bi_dram[0].size = low_end;
 
 	return 0;
 }
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 051/108] x86: Set up the MTRR for SDRAM
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (27 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 050/108] x86: Set the DRAM banks to reflect real location Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  2:23   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 052/108] x86: Don't imply libfdt or SPI flash in TPL Simon Glass
                   ` (58 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Set up MTRRs for the FST SDRAM regions to improve performance.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Move mtrr_add_request() call into this patch

Changes in v2: None

 arch/x86/lib/fsp/fsp_dram.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c
index 3ede9b73fe2..9ca898a0cd3 100644
--- a/arch/x86/lib/fsp/fsp_dram.c
+++ b/arch/x86/lib/fsp/fsp_dram.c
@@ -8,6 +8,7 @@
 #include <asm/fsp/fsp_support.h>
 #include <asm/e820.h>
 #include <asm/mrccache.h>
+#include <asm/mtrr.h>
 #include <asm/post.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -60,6 +61,8 @@ int dram_init_banksize(void)
 
 		gd->bd->bi_dram[bank].start = res_desc->phys_start;
 		gd->bd->bi_dram[bank].size = res_desc->len;
+		mtrr_add_request(MTRR_TYPE_WRBACK, res_desc->phys_start,
+				 res_desc->len);
 		log_debug("ram %llx %llx\n", gd->bd->bi_dram[bank].start,
 			  gd->bd->bi_dram[bank].size);
 	}
@@ -68,6 +71,8 @@ int dram_init_banksize(void)
 	gd->bd->bi_dram[0].start = 0;
 	gd->bd->bi_dram[0].size = low_end;
 
+	mtrr_add_request(MTRR_TYPE_WRBACK, 0, low_end);
+
 	return 0;
 }
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 052/108] x86: Don't imply libfdt or SPI flash in TPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (28 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 051/108] x86: Set up the MTRR for SDRAM Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  2:23   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 053/108] x86: Allow removal of standard PCH drivers Simon Glass
                   ` (57 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

We don't want to pull in libfdt if of-platdata is being used, since it
reduces the available code-size saves. Also, SPI flash is seldom needed
in TPL.

Drop these options.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Don't imply SPI flash either
- Rewrite commit message

Changes in v2: None

 arch/Kconfig | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 6865e1f909e..54de91afb34 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -204,14 +204,11 @@ config X86
 	imply SPL_SYSCON
 	# TPL
 	imply TPL_DM
-	imply TPL_OF_LIBFDT
 	imply TPL_DRIVERS_MISC_SUPPORT
 	imply TPL_GPIO_SUPPORT
 	imply TPL_LIBCOMMON_SUPPORT
 	imply TPL_LIBGENERIC_SUPPORT
 	imply TPL_SERIAL_SUPPORT
-	imply TPL_SPI_FLASH_SUPPORT
-	imply TPL_SPI_SUPPORT
 	imply TPL_OF_CONTROL
 	imply TPL_TIMER
 	imply TPL_REGMAP
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 053/108] x86: Allow removal of standard PCH drivers
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (29 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 052/108] x86: Don't imply libfdt or SPI flash in TPL Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 054/108] x86: Allow interrupt to happen once Simon Glass
                   ` (56 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

These drivers are not needed on all platforms. While they are small, it
is useful in TPL to drop then. Add Kconfig control to allow this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3: None
Changes in v2:
- Change 'queensbay' to 'baytrail' in help
- Fix 'proides' typo

 drivers/pch/Kconfig  | 18 ++++++++++++++++++
 drivers/pch/Makefile |  4 ++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/pch/Kconfig b/drivers/pch/Kconfig
index 18f006de24c..c49a92885aa 100644
--- a/drivers/pch/Kconfig
+++ b/drivers/pch/Kconfig
@@ -7,3 +7,21 @@ config PCH
 	  northbridge / southbridge architecture that was previously used. The
 	  PCH allows for higher performance since the memory functions are
 	  handled in the CPU.
+
+config X86_PCH7
+	bool "Add support for Intel PCH7"
+	default y if X86
+	help
+	  Enable this if your SoC uses Platform Controller Hub 7 (PCH7). This
+	  dates from about 2011 and is used on baytrail, for example. The
+	  PCH provides access to the GPIO and SPI base addresses, among other
+	  functions.
+
+config X86_PCH9
+	bool "Add support for Intel PCH9"
+	default y if X86
+	help
+	  Enable this if your SoC uses Platform Controller Hub 9 (PCH9). This
+	  dates from about 2015 and is used on baytrail, for example. The
+	  PCH provides access to the GPIO and SPI base addresses, among other
+	  functions.
diff --git a/drivers/pch/Makefile b/drivers/pch/Makefile
index 8ea6b7852ac..d5de3e48be1 100644
--- a/drivers/pch/Makefile
+++ b/drivers/pch/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 obj-y += pch-uclass.o
-obj-y += pch7.o
-obj-y += pch9.o
+obj-$(CONFIG_X86_PCH7) += pch7.o
+obj-$(CONFIG_X86_PCH9) += pch9.o
 obj-$(CONFIG_SANDBOX) += sandbox_pch.o
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 054/108] x86: Allow interrupt to happen once
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (30 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 053/108] x86: Allow removal of standard PCH drivers Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 055/108] x86: fsp: Make graphics support common to FSP1/2 Simon Glass
                   ` (55 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present the interrupt table is included in all phases of U-Boot. Allow
it to be omitted, e.g. in TPL, to reduce size.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3:
- Move write_pirq_routing_table() to avoid 64-bit build error

Changes in v2: None

 arch/x86/cpu/Makefile       |  2 +-
 arch/x86/cpu/irq.c          |  8 --------
 arch/x86/lib/pirq_routing.c | 10 ++++++++++
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 6296b55ff8a..b6a010ea320 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -53,7 +53,7 @@ obj-$(CONFIG_INTEL_QUARK) += quark/
 obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
 obj-$(CONFIG_INTEL_TANGIER) += tangier/
 obj-$(CONFIG_APIC) += lapic.o ioapic.o
-obj-y += irq.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += irq.o
 ifndef CONFIG_$(SPL_)X86_64
 obj-$(CONFIG_SMP) += mp_init.o
 endif
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
index cb183496b7a..ed9938f7f7f 100644
--- a/arch/x86/cpu/irq.c
+++ b/arch/x86/cpu/irq.c
@@ -350,14 +350,6 @@ int irq_router_probe(struct udevice *dev)
 	return 0;
 }
 
-ulong write_pirq_routing_table(ulong addr)
-{
-	if (!gd->arch.pirq_routing_table)
-		return addr;
-
-	return copy_pirq_routing_table(addr, gd->arch.pirq_routing_table);
-}
-
 static const struct udevice_id irq_router_ids[] = {
 	{ .compatible = "intel,irq-router" },
 	{ }
diff --git a/arch/x86/lib/pirq_routing.c b/arch/x86/lib/pirq_routing.c
index e5f0e614241..17bd2fcb9b4 100644
--- a/arch/x86/lib/pirq_routing.c
+++ b/arch/x86/lib/pirq_routing.c
@@ -10,6 +10,8 @@
 #include <asm/pci.h>
 #include <asm/pirq_routing.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 static u8 pirq_get_next_free_irq(struct udevice *dev, u8 *pirq, u16 bitmap,
 				 bool irq_already_routed[])
 {
@@ -131,3 +133,11 @@ u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt)
 
 	return addr + rt->size;
 }
+
+ulong write_pirq_routing_table(ulong addr)
+{
+	if (!gd->arch.pirq_routing_table)
+		return addr;
+
+	return copy_pirq_routing_table(addr, gd->arch.pirq_routing_table);
+}
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 055/108] x86: fsp: Make graphics support common to FSP1/2
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (31 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 054/108] x86: Allow interrupt to happen once Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  2:23   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 056/108] x86: fsp: Correct wrong header inlude in fsp_support.c Simon Glass
                   ` (54 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Both versions of FSP can use the same graphics support, so move it into
the common directory.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/lib/fsp/Makefile                 | 3 +++
 arch/x86/lib/{fsp1 => fsp}/fsp_graphics.c | 2 +-
 arch/x86/lib/fsp1/Makefile                | 1 -
 3 files changed, 4 insertions(+), 2 deletions(-)
 rename arch/x86/lib/{fsp1 => fsp}/fsp_graphics.c (98%)

diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile
index 9e348564737..da6c0a886ae 100644
--- a/arch/x86/lib/fsp/Makefile
+++ b/arch/x86/lib/fsp/Makefile
@@ -4,4 +4,7 @@
 
 obj-y += fsp_common.o
 obj-y += fsp_dram.o
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_VIDEO_FSP) += fsp_graphics.o
+endif
 obj-y += fsp_support.o
diff --git a/arch/x86/lib/fsp1/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
similarity index 98%
rename from arch/x86/lib/fsp1/fsp_graphics.c
rename to arch/x86/lib/fsp/fsp_graphics.c
index 52e71334f95..91d2d085572 100644
--- a/arch/x86/lib/fsp1/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -7,7 +7,7 @@
 #include <dm.h>
 #include <vbe.h>
 #include <video.h>
-#include <asm/fsp1/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/x86/lib/fsp1/Makefile b/arch/x86/lib/fsp1/Makefile
index 870de71bd71..1cf5e541913 100644
--- a/arch/x86/lib/fsp1/Makefile
+++ b/arch/x86/lib/fsp1/Makefile
@@ -5,5 +5,4 @@
 obj-y += fsp_car.o
 obj-y += fsp_common.o
 obj-y += fsp_dram.o
-obj-$(CONFIG_VIDEO_FSP) += fsp_graphics.o
 obj-y += fsp_support.o
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 056/108] x86: fsp: Correct wrong header inlude in fsp_support.c
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (32 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 055/108] x86: fsp: Make graphics support common to FSP1/2 Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  7:25   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support Simon Glass
                   ` (53 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

This generic FSP file should include the generic FSP support header, not
the FSP1 version. Fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/lib/fsp/fsp_support.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index 983888fd743..ee228117d13 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -5,7 +5,7 @@
  */
 
 #include <common.h>
-#include <asm/fsp1/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 #include <asm/post.h>
 
 u32 fsp_get_usable_lowmem_top(const void *hob_list)
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (33 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 056/108] x86: fsp: Correct wrong header inlude in fsp_support.c Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  7:25   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 058/108] x86: fsp: Set up an MTRR for the graphics frame buffer Simon Glass
                   ` (52 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add support for some important configuration options and FSP memory init.
The memory init uses swizzle tables from the device tree.

Support for the FSP_S binary is also included.

Bootstage timing is used for both FSP_M and FSP_M and memory-mapped SPI
reads.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add a proper implementation of fsp_notify
- Add an fsp: tag
- Add bootstage timing for memory-mapped reads
- Add fsp_locate_fsp to locate an fsp component
- Add fspm_done() hook
- Add support for FSP-S component and VBT
- Simplify types for fsp_locate_fsp()
- Switch mmap to use SPI instead of SPI flash

Changes in v2: None

 arch/x86/Kconfig                         |  61 ++++++++-
 arch/x86/include/asm/fsp2/fsp_api.h      |  60 +++++++++
 arch/x86/include/asm/fsp2/fsp_internal.h |  97 ++++++++++++++
 arch/x86/lib/fsp2/Makefile               |  10 ++
 arch/x86/lib/fsp2/fsp_common.c           |  13 ++
 arch/x86/lib/fsp2/fsp_dram.c             |  77 +++++++++++
 arch/x86/lib/fsp2/fsp_init.c             | 157 +++++++++++++++++++++++
 arch/x86/lib/fsp2/fsp_meminit.c          |  97 ++++++++++++++
 arch/x86/lib/fsp2/fsp_silicon_init.c     |  52 ++++++++
 arch/x86/lib/fsp2/fsp_support.c          | 129 +++++++++++++++++++
 include/bootstage.h                      |   3 +
 11 files changed, 754 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/include/asm/fsp2/fsp_api.h
 create mode 100644 arch/x86/include/asm/fsp2/fsp_internal.h
 create mode 100644 arch/x86/lib/fsp2/Makefile
 create mode 100644 arch/x86/lib/fsp2/fsp_common.c
 create mode 100644 arch/x86/lib/fsp2/fsp_dram.c
 create mode 100644 arch/x86/lib/fsp2/fsp_init.c
 create mode 100644 arch/x86/lib/fsp2/fsp_meminit.c
 create mode 100644 arch/x86/lib/fsp2/fsp_silicon_init.c
 create mode 100644 arch/x86/lib/fsp2/fsp_support.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 17a6fe6d3d9..cbd3fc4f581 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -326,7 +326,7 @@ config X86_RAMTEST
 
 config FLASH_DESCRIPTOR_FILE
 	string "Flash descriptor binary filename"
-	depends on HAVE_INTEL_ME
+	depends on HAVE_INTEL_ME || FSP_VERSION2
 	default "descriptor.bin"
 	help
 	  The filename of the file to use as flash descriptor in the
@@ -411,6 +411,63 @@ config FSP_ADDR
 	  The default base address of 0xfffc0000 indicates that the binary must
 	  be located at offset 0xc0000 from the beginning of a 1MB flash device.
 
+if FSP_VERSION2
+
+config FSP_FILE_T
+	string "Firmware-Support-Package binary filename (Temp RAM)"
+	default "fsp_t.bin"
+	help
+	  The filename of the file to use for the temporary-RAM init phase from
+	  the Firmware-Support-Package binary. Put this in the board directory.
+	  It is used to set up an initial area of RAM which can be used for the
+	  stack and other purposes, while bringing up the main system DRAM.
+
+config FSP_ADDR_T
+	hex "Firmware-Support-Package binary location (Temp RAM)"
+	default 0xffff8000
+	help
+	  FSP is not Position-Independent Code (PIC) and FSP components have to
+	  be rebased if placed at a location which is different from the
+	  perferred base address specified during the FSP build. Use Intel's
+	  Binary Configuration Tool (BCT) to do the rebase.
+
+config FSP_FILE_M
+	string "Firmware-Support-Package binary filename (Memory Init)"
+	default "fsp_m.bin"
+	help
+	  The filename of the file to use for the RAM init phase from the
+	  Firmware Support Package binary. Put this in the board directory.
+	  It is used to set up the main system DRAM and runs in SPL, once
+	  temporary RAM (CAR) is working.
+
+config FSP_FILE_S
+	string "Firmware-Support-Package binary filename (Silicon Init)"
+	default "fsp_s.bin"
+	help
+	  The filename of the file to use for the Silicon init phase from the
+	  Firmware Support Package binary. Put this in the board directory.
+	  It is used to set up the silicon to work correctly and must be
+	  executed after DRAM is running.
+
+config FSP_FILE_VBT
+	string "Firmware-Support-Package Video BIOS Table (VBT)"
+	default "vbt.bin"
+	help
+	  The filename of the file to use for the video data needd by the
+	  Silicon init phase from the Firmware Support Package binary. Put this
+	  in the board directory. It is used to set up the video parameters so
+	  that the display can be used.
+
+config IFWI_INPUT_FILE
+	string "Filename containing FIT (Firmware Interface Table) with IFWI"
+	default "fitimage.bin"
+	help
+	  The IFWI is obtained by running a tool on this file to extract the
+	  IFWI. Put this in the board directory. The IFWI contains U-Boot TPL,
+	  microcode and other internal items.
+
+endif
+
 config FSP_TEMP_RAM_ADDR
 	hex
 	depends on FSP_VERSION1
@@ -629,7 +686,7 @@ config VBT_ADDR
 
 config VIDEO_FSP
 	bool "Enable FSP framebuffer driver support"
-	depends on HAVE_VBT && DM_VIDEO
+	depends on (HAVE_VBT || FSP_VERSION2) && DM_VIDEO
 	help
 	  Turn on this option to enable a framebuffer driver when U-Boot is
 	  using Video BIOS Table (VBT) image for FSP firmware to initialize
diff --git a/arch/x86/include/asm/fsp2/fsp_api.h b/arch/x86/include/asm/fsp2/fsp_api.h
new file mode 100644
index 00000000000..93b6472dce0
--- /dev/null
+++ b/arch/x86/include/asm/fsp2/fsp_api.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ * Mostly taken from coreboot fsp2_0/memory_init.c
+ */
+
+#ifndef __ASM_FSP2_API_H
+#define __ASM_FSP2_API_H
+
+#include <asm/fsp/fsp_api.h>
+
+struct fspm_upd;
+struct fsps_upd;
+struct hob_header;
+
+enum fsp_boot_mode {
+	FSP_BOOT_WITH_FULL_CONFIGURATION = 0x00,
+	FSP_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01,
+	FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02,
+	FSP_BOOT_ON_S4_RESUME = 0x05,
+	FSP_BOOT_ON_S3_RESUME = 0x11,
+	FSP_BOOT_ON_FLASH_UPDATE = 0x12,
+	FSP_BOOT_IN_RECOVERY_MODE = 0x20
+};
+
+struct __packed fsp_upd_header {
+	u64	signature;
+	u8	revision;
+	u8	reserved[23];
+};
+
+/**
+ * fsp_memory_init() - Init the SDRAM
+ *
+ * @s3wake: true if we are booting from resume, so cannot reinit the mememory
+ *	from scatch since we will lose its contents
+ * @use_spi_flash: true to use the fast SPI driver to read FSP, otherwise use
+ *	mapped SPI
+ * @return 0 if OK, -ve on error
+ */
+int fsp_memory_init(bool s3wake, bool use_spi_flash);
+
+typedef asmlinkage int (*fsp_memory_init_func)(struct fspm_upd *params,
+					       struct hob_header **hobp);
+
+/**
+ * fsp_silicon_init() - Init the silicon
+ *
+ * This calls the FSP's 'silicon init' entry point
+ *
+ * @s3wake: true if we are booting from resume
+ * @return 0 if OK, -ve on error
+ */
+int fsp_silicon_init(bool s3wake, bool use_spi_flash);
+
+typedef asmlinkage int (*fsp_silicon_init_func)(struct fsps_upd *params);
+
+#endif
diff --git a/arch/x86/include/asm/fsp2/fsp_internal.h b/arch/x86/include/asm/fsp2/fsp_internal.h
new file mode 100644
index 00000000000..5893f1ffcc7
--- /dev/null
+++ b/arch/x86/include/asm/fsp2/fsp_internal.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ * Mostly taken from coreboot
+ */
+
+#ifndef __ASM_FSP_INTERNAL_H
+#define __ASM_FSP_INTERNAL_H
+
+struct binman_entry;
+struct fsp_header;
+struct fspm_upd;
+struct fsps_upd;
+
+enum fsp_type_t {
+	FSP_M,
+	FSP_S,
+};
+
+int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
+		   struct fsp_header **fspp);
+
+/**
+ * fsp_locate_fsp() - Locate an FSP component
+ *
+ * This finds an FSP component by various methods. It is not as general-purpose
+ * as it looks, since it expects FSP-M to be requested in SPL (only), and FSP-S
+ * to be requested in U-Boot proper.
+ *
+ * @type: Component to locate
+ * @entry: Returns location of component
+ * @use_spi_flash: true to read using the Fast SPI driver, false to use
+ *	memory-mapped SPI flash
+ * @devp: Returns northbridge device
+ * @hdrp: Returns FSP header
+ * @rom_offsetp: If non-NULL, returns the offset to add to any image position to
+ *	find the memory-mapped location of that position. For example, for ROM
+ *	position 0x1000, it will be mapped into 0x1000 + *rom_offsetp.
+ */
+int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
+		   bool use_spi_flash, struct udevice **devp,
+		   struct fsp_header **hdrp, ulong *rom_offsetp);
+
+/**
+ * arch_fsp_s_preinit() - Perform init needed before calling FSP-S
+ *
+ * This allows use of probed drivers and PCI so is a convenient place to do any
+ * init that is needed before FSP-S is called. After this, U-Boot relocates and
+ * calls arch_fsp_init_r() before PCI is probed, and that function is not
+ * allowed to probe PCI before calling FSP-S.
+ */
+int arch_fsp_s_preinit(void);
+
+/**
+ * fspm_update_config() - Set up the config structure for FSP-M
+ *
+ * @dev: Hostbridge device containing config
+ * @upd: Config data to fill in
+ * @return 0 if OK, -ve on error
+ */
+int fspm_update_config(struct udevice *dev, struct fspm_upd *upd);
+
+/**
+ * fspm_done() - Indicate that memory init is complete
+ *
+ * This allows the board to do whatever post-init it needs before things
+ * continue.
+ *
+ * @dev: Hostbridge device
+ * @return 0 if OK, -ve on error
+ */
+int fspm_done(struct udevice *dev);
+
+/**
+ * fsps_update_config() - Set up the config structure for FSP-S
+ *
+ * @dev: Hostbridge device containing config
+ * @rom_offset: Value to add to convert from ROM offset to memory-mapped address
+ * @upd: Config data to fill in
+ * @return 0 if OK, -ve on error
+ */
+int fsps_update_config(struct udevice *dev, ulong rom_offset,
+		       struct fsps_upd *upd);
+
+/**
+ * prepare_mrc_cache() - Read the MRC cache into the product-data struct
+ *
+ * This looks for cached Memory-reference code (MRC) data and stores it into
+ * @upd for use by the FSP-M binary.
+ *
+ * @return 0 if OK, -ENOENT if no data (whereupon the caller can continue and
+ *	expect a slower boot), other -ve value on other error
+ */
+int prepare_mrc_cache(struct fspm_upd *upd);
+
+#endif
diff --git a/arch/x86/lib/fsp2/Makefile b/arch/x86/lib/fsp2/Makefile
new file mode 100644
index 00000000000..ddbe2d0db26
--- /dev/null
+++ b/arch/x86/lib/fsp2/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2019 Google LLC
+
+obj-y += fsp_common.o
+obj-y += fsp_dram.o
+obj-y += fsp_init.o
+obj-y += fsp_meminit.o
+obj-y += fsp_silicon_init.o
+obj-y += fsp_support.o
diff --git a/arch/x86/lib/fsp2/fsp_common.c b/arch/x86/lib/fsp2/fsp_common.c
new file mode 100644
index 00000000000..f69456e43a2
--- /dev/null
+++ b/arch/x86/lib/fsp2/fsp_common.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <init.h>
+
+int arch_fsp_init(void)
+{
+	return 0;
+}
diff --git a/arch/x86/lib/fsp2/fsp_dram.c b/arch/x86/lib/fsp2/fsp_dram.c
new file mode 100644
index 00000000000..a3f95d0cf96
--- /dev/null
+++ b/arch/x86/lib/fsp2/fsp_dram.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <acpi_s3.h>
+#include <handoff.h>
+#include <spl.h>
+#include <asm/arch/cpu.h>
+#include <asm/fsp/fsp_support.h>
+#include <asm/fsp2/fsp_api.h>
+#include <asm/fsp2/fsp_internal.h>
+
+int dram_init(void)
+{
+	int ret;
+
+	if (spl_phase() == PHASE_SPL) {
+#ifdef CONFIG_HAVE_ACPI_RESUME
+		bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
+#else
+		bool s3wake = false;
+#endif
+
+		ret = fsp_memory_init(s3wake, BOOT_FROM_FAST_SPI_FLASH);
+		if (ret) {
+			debug("Memory init failed (err=%x)\n", ret);
+			return ret;
+		}
+
+		/* The FSP has already set up DRAM, so grab the info we need */
+		ret = fsp_scan_for_ram_size();
+		if (ret)
+			return ret;
+
+#ifdef CONFIG_ENABLE_MRC_CACHE
+		gd->arch.mrc[MRC_TYPE_NORMAL].buf =
+			fsp_get_nvs_data(gd->arch.hob_list,
+					 &gd->arch.mrc[MRC_TYPE_NORMAL].len);
+		gd->arch.mrc[MRC_TYPE_VAR].buf =
+			fsp_get_var_nvs_data(gd->arch.hob_list,
+					     &gd->arch.mrc[MRC_TYPE_VAR].len);
+		log_debug("normal %x, var %x\n",
+			  gd->arch.mrc[MRC_TYPE_NORMAL].len,
+			  gd->arch.mrc[MRC_TYPE_VAR].len);
+#endif
+	} else {
+#if CONFIG_IS_ENABLED(HANDOFF)
+		struct spl_handoff *ho = gd->spl_handoff;
+
+		if (!ho) {
+			debug("No SPL handoff found\n");
+			return -ESTRPIPE;
+		}
+		gd->ram_size = ho->ram_size;
+		handoff_load_dram_banks(ho);
+#endif
+		ret = arch_fsp_s_preinit();
+		if (ret)
+			return log_msg_ret("fsp_s_preinit", ret);
+	}
+
+	return 0;
+}
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+#if CONFIG_IS_ENABLED(HANDOFF)
+	struct spl_handoff *ho = gd->spl_handoff;
+
+	return ho->arch.usable_ram_top;
+#endif
+
+	return gd->ram_top;
+}
diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c
new file mode 100644
index 00000000000..111eb51d34b
--- /dev/null
+++ b/arch/x86/lib/fsp2/fsp_init.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <binman_sym.h>
+#include <cbfs.h>
+#include <dm.h>
+#include <init.h>
+#include <spi.h>
+#include <spl.h>
+#include <spi_flash.h>
+#include <asm/arch/gpio.h>
+#include <dm/uclass-internal.h>
+#include <asm/fsp2/fsp_internal.h>
+
+int arch_cpu_init_dm(void)
+{
+	struct udevice *dev;
+	ofnode node;
+	int ret;
+
+	if (spl_phase() != PHASE_BOARD_F)
+		return 0;
+
+	/* Probe all GPIO devices to set up the pads */
+	ret = uclass_first_device_err(UCLASS_GPIO, &dev);
+	if (ret)
+		return log_msg_ret("no fsp GPIO", ret);
+	node = ofnode_path("fsp");
+	if (!ofnode_valid(node))
+		return log_msg_ret("no fsp params", -EINVAL);
+	ret = hostbridge_config_pads_for_node(dev, node);
+	if (ret)
+		return log_msg_ret("pad config", ret);
+
+	return ret;
+}
+
+#if !defined(CONFIG_TPL_BUILD)
+binman_sym_declare(ulong, intel_fsp_m, image_pos);
+binman_sym_declare(ulong, intel_fsp_m, size);
+
+static int get_coreboot_fsp(enum fsp_type_t type, ulong map_base,
+			    struct binman_entry *entry)
+{
+	/* Hard-coded position of CBFS in ROM */
+	ulong cbfs_base = 0x205000;
+	ulong cbfs_size = 0x1bb000;
+	struct cbfs_priv *cbfs;
+	int ret;
+
+	ret = cbfs_init_mem(map_base + cbfs_base, cbfs_size, &cbfs);
+	if (ret)
+		return ret;
+	if (!ret) {
+		const struct cbfs_cachenode *node;
+
+		node = cbfs_find_file(cbfs, "fspm.bin");
+		if (!node)
+			return log_msg_ret("fspm node", -ENOENT);
+
+		entry->image_pos = (ulong)node->data;
+		entry->size = node->data_length;
+	}
+
+	return 0;
+}
+
+int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
+		   bool use_spi_flash, struct udevice **devp,
+		   struct fsp_header **hdrp, ulong *rom_offsetp)
+{
+	ulong mask = CONFIG_ROM_SIZE - 1;
+	struct udevice *dev;
+	ulong rom_offset = 0;
+	uint map_size;
+	ulong map_base;
+	uint offset;
+	int ret;
+
+	/*
+	 * Find the devices but don't probe them, since we don't want to
+	 * auto-config PCI before silicon init runs
+	 */
+	ret = uclass_find_first_device(UCLASS_NORTHBRIDGE, &dev);
+	if (ret)
+		return log_msg_ret("Cannot get northbridge", ret);
+	if (!use_spi_flash) {
+		struct udevice *sf;
+
+		/* Just use the SPI driver to get the memory map */
+		ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf);
+		if (ret)
+			return log_msg_ret("Cannot get SPI flash", ret);
+		ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset);
+		if (ret)
+			return log_msg_ret("Could not get flash mmap", ret);
+	}
+
+	if (spl_phase() >= PHASE_BOARD_F) {
+		if (type != FSP_S)
+			return -EPROTONOSUPPORT;
+		ret = binman_entry_find("intel-fsp-s", entry);
+		if (ret)
+			return log_msg_ret("binman entry", ret);
+		if (!use_spi_flash)
+			rom_offset = (map_base & mask) - CONFIG_ROM_SIZE;
+	} else {
+		ret = -ENOENT;
+		if (false)
+			/* Support using a hybrid image build by coreboot */
+			ret = get_coreboot_fsp(type, map_base, entry);
+		if (ret) {
+			ulong mask = CONFIG_ROM_SIZE - 1;
+
+			if (type != FSP_M)
+				return -EPROTONOSUPPORT;
+			entry->image_pos = binman_sym(ulong, intel_fsp_m,
+						      image_pos);
+			entry->size = binman_sym(ulong, intel_fsp_m, size);
+			if (entry->image_pos != BINMAN_SYM_MISSING) {
+				ret = 0;
+				if (use_spi_flash)
+					entry->image_pos &= mask;
+				else
+					entry->image_pos += (map_base & mask);
+			} else {
+				ret = -ENOENT;
+			}
+		}
+	}
+	if (ret)
+		return log_msg_ret("Cannot find FSP", ret);
+	entry->image_pos += rom_offset;
+
+	/*
+	 * Account for the time taken to read memory-mapped SPI flash since in
+	 * this case we don't use the SPI driver and BOOTSTAGE_ID_ACCUM_SPI.
+	 */
+	if (!use_spi_flash)
+		bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
+	ret = fsp_get_header(entry->image_pos, entry->size, use_spi_flash,
+			     hdrp);
+	if (!use_spi_flash)
+		bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
+	if (ret)
+		return log_msg_ret("fsp_get_header", ret);
+	*devp = dev;
+	if (rom_offsetp)
+		*rom_offsetp = rom_offset;
+
+	return 0;
+}
+#endif
diff --git a/arch/x86/lib/fsp2/fsp_meminit.c b/arch/x86/lib/fsp2/fsp_meminit.c
new file mode 100644
index 00000000000..bf30c479899
--- /dev/null
+++ b/arch/x86/lib/fsp2/fsp_meminit.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ * Mostly taken from coreboot fsp2_0/memory_init.c
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <asm/mrccache.h>
+#include <asm/fsp/fsp_infoheader.h>
+#include <asm/fsp2/fsp_api.h>
+#include <asm/fsp2/fsp_internal.h>
+#include <asm/arch/fsp/fsp_configs.h>
+#include <asm/arch/fsp/fsp_m_upd.h>
+
+static int prepare_mrc_cache_type(enum mrc_type_t type,
+				  struct mrc_data_container **cachep)
+{
+	struct mrc_data_container *cache;
+	struct mrc_region entry;
+	int ret;
+
+	ret = mrccache_get_region(type, NULL, &entry);
+	if (ret)
+		return ret;
+	cache = mrccache_find_current(&entry);
+	if (!cache)
+		return -ENOENT;
+
+	log_debug("MRC at %x, size %x\n", (uint)cache->data, cache->data_size);
+	*cachep = cache;
+
+	return 0;
+}
+
+int prepare_mrc_cache(struct fspm_upd *upd)
+{
+	struct mrc_data_container *cache;
+	int ret;
+
+	ret = prepare_mrc_cache_type(MRC_TYPE_NORMAL, &cache);
+	if (ret)
+		return log_msg_ret("Cannot get normal cache", ret);
+	upd->arch.nvs_buffer_ptr = cache->data;
+
+	ret = prepare_mrc_cache_type(MRC_TYPE_VAR, &cache);
+	if (ret)
+		return log_msg_ret("Cannot get var cache", ret);
+	upd->config.variable_nvs_buffer_ptr = cache->data;
+
+	return 0;
+}
+
+int fsp_memory_init(bool s3wake, bool use_spi_flash)
+{
+	struct fspm_upd upd, *fsp_upd;
+	fsp_memory_init_func func;
+	struct binman_entry entry;
+	struct fsp_header *hdr;
+	struct hob_header *hob;
+	struct udevice *dev;
+	int ret;
+
+	ret = fsp_locate_fsp(FSP_M, &entry, use_spi_flash, &dev, &hdr, NULL);
+	if (ret)
+		return log_msg_ret("locate FSP", ret);
+	debug("Found FSP_M at %x, size %x\n", hdr->img_base, hdr->img_size);
+
+	/* Copy over the default config */
+	fsp_upd = (struct fspm_upd *)(hdr->img_base + hdr->cfg_region_off);
+	if (fsp_upd->header.signature != FSPM_UPD_SIGNATURE)
+		return log_msg_ret("Bad UPD signature", -EPERM);
+	memcpy(&upd, fsp_upd, sizeof(upd));
+
+	ret = fspm_update_config(dev, &upd);
+	if (ret)
+		return log_msg_ret("Could not setup config", ret);
+
+	debug("SDRAM init...");
+	bootstage_start(BOOTSTATE_ID_ACCUM_FSP_M, "fsp-m");
+	func = (fsp_memory_init_func)(hdr->img_base + hdr->fsp_mem_init);
+	ret = func(&upd, &hob);
+	bootstage_accum(BOOTSTATE_ID_ACCUM_FSP_M);
+	if (ret)
+		return log_msg_ret("SDRAM init fail\n", ret);
+
+	gd->arch.hob_list = hob;
+	debug("done\n");
+
+	ret = fspm_done(dev);
+	if (ret)
+		return log_msg_ret("fsm_done\n", ret);
+
+	return 0;
+}
diff --git a/arch/x86/lib/fsp2/fsp_silicon_init.c b/arch/x86/lib/fsp2/fsp_silicon_init.c
new file mode 100644
index 00000000000..c758e80c383
--- /dev/null
+++ b/arch/x86/lib/fsp2/fsp_silicon_init.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
+ *
+ * Mostly taken from coreboot fsp2_0/silicon_init.c
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <dm.h>
+#include <asm/arch/fsp/fsp_configs.h>
+#include <asm/arch/fsp/fsp_s_upd.h>
+#include <asm/fsp/fsp_infoheader.h>
+#include <asm/fsp2/fsp_internal.h>
+
+int fsp_silicon_init(bool s3wake, bool use_spi_flash)
+{
+	struct fsps_upd upd, *fsp_upd;
+	fsp_silicon_init_func func;
+	struct fsp_header *hdr;
+	struct binman_entry entry;
+	struct udevice *dev;
+	ulong rom_offset = 0;
+	int ret;
+
+	ret = fsp_locate_fsp(FSP_S, &entry, use_spi_flash, &dev, &hdr,
+			     &rom_offset);
+	if (ret)
+		return log_msg_ret("locate FSP", ret);
+	gd->arch.fsp_s_hdr = hdr;
+
+	/* Copy over the default config */
+	fsp_upd = (struct fsps_upd *)(hdr->img_base + hdr->cfg_region_off);
+	if (fsp_upd->header.signature != FSPS_UPD_SIGNATURE)
+		return log_msg_ret("Bad UPD signature", -EPERM);
+	memcpy(&upd, fsp_upd, sizeof(upd));
+
+	ret = fsps_update_config(dev, rom_offset, &upd);
+	if (ret)
+		return log_msg_ret("Could not setup config", ret);
+	log_debug("Silicon init...");
+	bootstage_start(BOOTSTATE_ID_ACCUM_FSP_S, "fsp-s");
+	func = (fsp_silicon_init_func)(hdr->img_base + hdr->fsp_silicon_init);
+	ret = func(&upd);
+	bootstage_accum(BOOTSTATE_ID_ACCUM_FSP_S);
+	if (ret)
+		return log_msg_ret("Silicon init fail\n", ret);
+	log_debug("done\n");
+
+	return 0;
+}
diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c
new file mode 100644
index 00000000000..477eaa268db
--- /dev/null
+++ b/arch/x86/lib/fsp2/fsp_support.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi_flash.h>
+#include <asm/fsp/fsp_support.h>
+#include <asm/fsp2/fsp_internal.h>
+
+/* The amount of the FSP header to probe to obtain what we need */
+#define PROBE_BUF_SIZE 0x180
+
+/* Not needed in SPL apparently */
+#define SAFETY_MARGIN	0
+
+int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
+		   struct fsp_header **fspp)
+{
+	static efi_guid_t guid = FSP_HEADER_GUID;
+	struct fv_ext_header *exhdr;
+	struct fsp_header *fsp;
+	struct ffs_file_header *file_hdr;
+	struct fv_header *fv;
+	struct raw_section *raw;
+	void *ptr, *base;
+	u8 buf[PROBE_BUF_SIZE];
+	struct udevice *dev;
+	int ret;
+
+	/* You are in a maze of twisty headers all alike */
+	debug("offset=%x buf=%x\n", (uint)offset, (uint)buf);
+	if (use_spi_flash) {
+		ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
+		if (ret)
+			return log_msg_ret("Cannot find flash device", ret);
+		ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
+		if (ret)
+			return log_msg_ret("Cannot read flash", ret);
+	} else {
+		memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
+	}
+
+	/* Initalise the FSP base */
+	ptr = buf;
+	fv = ptr;
+
+	/* Check the FV signature, _FVH */
+	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);
+	ptr += fv->ext_hdr_off;
+	exhdr = ptr;
+	ptr += ALIGN(exhdr->ext_hdr_size, 8);
+	debug("ptr=%x\n", ptr - (void *)buf);
+
+	/* Check the FFS GUID */
+	file_hdr = ptr;
+	if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
+		return log_msg_ret("Base FFS GUID", -ENXIO);
+	/* Add the FFS header size to find the raw section header */
+	ptr = file_hdr + 1;
+
+	raw = ptr;
+	debug("raw->type = %x\n", raw->type);
+	if (raw->type != EFI_SECTION_RAW)
+		return log_msg_ret("Section type not RAW", -ENOEXEC);
+
+	/* Add the raw section header size to find the FSP header */
+	ptr = raw + 1;
+	fsp = ptr;
+
+	/* Check the FSPH header */
+	debug("fsp %x\n", (uint)fsp);
+	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);
+	if (use_spi_flash) {
+		ret = spi_flash_read_dm(dev, offset, size + SAFETY_MARGIN,
+					base);
+		if (ret)
+			return log_msg_ret("Could not read FPS-M", ret);
+	} else {
+		memcpy(base, (void *)offset, size + SAFETY_MARGIN);
+	}
+	ptr = base + (ptr - (void *)buf);
+	*fspp = ptr;
+
+	return 0;
+}
+
+u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
+{
+	fsp_notify_f notify;
+	struct fsp_notify_params params;
+	struct fsp_notify_params *params_ptr;
+	u32 status;
+
+	if (!fsp_hdr)
+		fsp_hdr = gd->arch.fsp_s_hdr;
+
+	if (!fsp_hdr)
+		return log_msg_ret("no FSP", -ENOENT);
+
+	notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
+	params.phase = phase;
+	params_ptr = &params;
+
+	/*
+	 * Use ASM code to ensure correct parameter is on the stack for
+	 * FspNotify as U-Boot is using different ABI from FSP
+	 */
+	asm volatile (
+		"pushl	%1;"		/* push notify phase */
+		"call	*%%eax;"	/* call FspNotify */
+		"addl	$4, %%esp;"	/* clean up the stack */
+		: "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
+	);
+
+	return status;
+}
diff --git a/include/bootstage.h b/include/bootstage.h
index 5e7e242b834..c271d3a6cc8 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -200,6 +200,9 @@ enum bootstage_id {
 	BOOTSTATE_ID_ACCUM_DM_SPL,
 	BOOTSTATE_ID_ACCUM_DM_F,
 	BOOTSTATE_ID_ACCUM_DM_R,
+	BOOTSTATE_ID_ACCUM_FSP_M,
+	BOOTSTATE_ID_ACCUM_FSP_S,
+	BOOTSTAGE_ID_ACCUM_MMAP_SPI,
 
 	/* a few spare for the user, from here */
 	BOOTSTAGE_ID_USER,
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 058/108] x86: fsp: Set up an MTRR for the graphics frame buffer
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (34 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  7:25   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 059/108] x86: fsp: Add a new arch_fsp_init_r() hook Simon Glass
                   ` (51 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

The FSP-S may do this but at least for coral it does not. Set this up so
that graphics is not deathly slow.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/lib/fsp/fsp_graphics.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
index 91d2d085572..226c7e66b3f 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -8,6 +8,7 @@
 #include <vbe.h>
 #include <video.h>
 #include <asm/fsp/fsp_support.h>
+#include <asm/mtrr.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -97,6 +98,9 @@ static int fsp_video_probe(struct udevice *dev)
 	if (ret)
 		goto err;
 
+	mtrr_add_request(MTRR_TYPE_WRCOMB, vesa->phys_base_ptr, 256 << 20);
+	mtrr_commit(true);
+
 	printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
 	       vesa->bits_per_pixel);
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 059/108] x86: fsp: Add a new arch_fsp_init_r() hook
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (35 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 058/108] x86: fsp: Set up an MTRR for the graphics frame buffer Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  7:25   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 060/108] x86: fsp: Allow remembering the location of FSP-S Simon Glass
                   ` (50 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

With FSP2 we need to run silicon init early after relocation. Add a new
hook for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 common/board_r.c |  3 +++
 include/init.h   | 11 +++++++++++
 2 files changed, 14 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index e0f3eb325aa..e6fda426eeb 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -703,6 +703,9 @@ static init_fnc_t init_sequence_r[] = {
 	efi_memory_init,
 #endif
 	initr_binman,
+#ifdef CONFIG_FSP_VERSION2
+	arch_fsp_init_r,
+#endif
 	stdio_init_tables,
 	initr_serial,
 	initr_announce,
diff --git a/include/init.h b/include/init.h
index afc953d51e2..43602029bc1 100644
--- a/include/init.h
+++ b/include/init.h
@@ -65,6 +65,17 @@ int mach_cpu_init(void);
  */
 int arch_fsp_init(void);
 
+/**
+ * arch_fsp_init() - perform post-relocation firmware support package init
+ *
+ * Where U-Boot relies on binary blobs to handle part of the system init, this
+ * function can be used to set up the blobs. This is used on some Intel
+ * platforms.
+ *
+ * Return: 0
+ */
+int arch_fsp_init_r(void);
+
 int dram_init(void);
 
 /**
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 060/108] x86: fsp: Allow remembering the location of FSP-S
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (36 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 059/108] x86: fsp: Add a new arch_fsp_init_r() hook Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  7:25   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 061/108] x86: fsp: Make the notify API call common Simon Glass
                   ` (49 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

FSP-S is used by the notify call after it has been used for silicon init.
To avoid having to load it again, add a field to store the location.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/global_data.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 6d21ddc0d1e..d8b5ed3a759 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -119,6 +119,9 @@ struct arch_global_data {
 	int prev_sleep_state;		/* Previous sleep state ACPI_S0/1../5 */
 	ulong backup_mem;		/* Backup memory address for S3 */
 #endif
+#ifdef CONFIG_FSP_VERSION2
+	struct fsp_header *fsp_s_hdr;	/* Pointer to FSP-S header */
+#endif
 };
 
 #endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 061/108] x86: fsp: Make the notify API call common
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (37 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 060/108] x86: fsp: Allow remembering the location of FSP-S Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:02   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 062/108] x86: Don't include the BIOS emulator in TPL Simon Glass
                   ` (48 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

The fsp_notify() API is the same for FSP1 and FSP2. Move it into a new
common API file.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/fsp/fsp_api.h  | 27 +++++++++++++++++++++++++++
 arch/x86/include/asm/fsp1/fsp_api.h | 21 +++------------------
 2 files changed, 30 insertions(+), 18 deletions(-)
 create mode 100644 arch/x86/include/asm/fsp/fsp_api.h

diff --git a/arch/x86/include/asm/fsp/fsp_api.h b/arch/x86/include/asm/fsp/fsp_api.h
new file mode 100644
index 00000000000..541f86ff0e8
--- /dev/null
+++ b/arch/x86/include/asm/fsp/fsp_api.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ * Mostly taken from coreboot fsp2_0/memory_init.c
+ */
+
+#ifndef __ASM_FSP_API_H
+#define __ASM_FSP_API_H
+
+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
+};
+
+struct fsp_notify_params {
+	/* Notification phase used for NotifyPhase API */
+	enum fsp_phase	phase;
+};
+
+/* FspNotify API function prototype */
+typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
+
+#endif
diff --git a/arch/x86/include/asm/fsp1/fsp_api.h b/arch/x86/include/asm/fsp1/fsp_api.h
index f2d70799f33..524da5feb75 100644
--- a/arch/x86/include/asm/fsp1/fsp_api.h
+++ b/arch/x86/include/asm/fsp1/fsp_api.h
@@ -4,11 +4,11 @@
  * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
  */
 
-#ifndef __FSP_API_H__
-#define __FSP_API_H__
+#ifndef __FSP1_API_H__
+#define __FSP1_API_H__
 
 #include <linux/linkage.h>
-
+#include <asm/fsp/fsp_api.h>
 /*
  * FSP common configuration structure.
  * This needs to be included in the platform-specific struct fsp_config_data.
@@ -46,22 +46,7 @@ struct common_buf {
 	u32	reserved[6];	/* Reserved */
 };
 
-enum fsp_phase {
-	/* Notification code for post PCI enuermation */
-	INIT_PHASE_PCI	= 0x20,
-	/* Notification code before transfering control to the payload */
-	INIT_PHASE_BOOT	= 0x40
-};
-
-struct fsp_notify_params {
-	/* Notification phase used for NotifyPhase API */
-	enum fsp_phase	phase;
-};
-
 /* FspInit API function prototype */
 typedef asmlinkage u32 (*fsp_init_f)(struct fsp_init_params *params);
 
-/* FspNotify API function prototype */
-typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
-
 #endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 062/108] x86: Don't include the BIOS emulator in TPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (38 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 061/108] x86: fsp: Make the notify API call common Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 063/108] x86: Add an option to include a FIT Simon Glass
                   ` (47 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

We don't generally have enough space to run this, so don't build it into
TPL. This helps reduce the size of TPL.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3: None
Changes in v2: None

 arch/x86/lib/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index ca0ca1066b0..5cd45874803 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -4,9 +4,11 @@
 # Wolfgang Denk, DENX Software Engineering, wd at denx.de.
 
 ifndef CONFIG_X86_64
+ifndef CONFIG_TPL_BUILD
 obj-y += bios.o
 obj-y += bios_asm.o
 obj-y += bios_interrupts.o
+endif
 obj-y += string.o
 endif
 ifndef CONFIG_SPL_BUILD
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 063/108] x86: Add an option to include a FIT
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (39 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 062/108] x86: Don't include the BIOS emulator in TPL Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:02   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes Simon Glass
                   ` (46 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Many Intel SoCs require a FIT in order to boot properly. Add an option to
include this and enable it by default.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add help to CONFIG_FIT and don't make it 'default y'

Changes in v2: None

 arch/x86/Kconfig         | 9 +++++++++
 arch/x86/dts/u-boot.dtsi | 6 ++++++
 2 files changed, 15 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cbd3fc4f581..54f51e002b8 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -217,6 +217,15 @@ config SYS_X86_START16
 	depends on X86_RESET_VECTOR
 	default 0xfffff800
 
+config X86_HAS_FIT
+	bool
+	default y
+	help
+	  Enable inclusion of an Intel Firmware Interface Table (FIT) into the
+	  image. This table is supposed to point to microcode and the like. So
+	  far it is just a fixed table with the minimum set of headers, so that
+	  it is actually present.
+
 config X86_LOAD_FROM_32_BIT
 	bool "Boot from a 32-bit program"
 	help
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 0e87b88e105..049f47c9ffd 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -82,6 +82,12 @@
 	u-boot-ucode {
 		align = <16>;
 	};
+#ifdef CONFIG_X86_HAS_FIT
+	intel-fit {
+	};
+	intel-fit-ptr {
+	};
+#endif
 #ifdef CONFIG_HAVE_MRC
 	intel-mrc {
 		offset = <CONFIG_X86_MRC_ADDR>;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (40 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 063/108] x86: Add an option to include a FIT Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  8:11   ` Andy Shevchenko
  2019-11-19  8:02   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 065/108] x86: Disable microcode section for FSP2 Simon Glass
                   ` (45 subsequent siblings)
  87 siblings, 2 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Newer Intel SoCs have different ways of setting up cache-as-ram (CAR).
Add support for these along with suitable configuration options.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Drop unneeded Kconfig file

Changes in v2: None

 arch/x86/Kconfig                        |  16 +
 arch/x86/cpu/intel_common/Makefile      |   8 +
 arch/x86/cpu/intel_common/car2.S        | 490 ++++++++++++++++++++++++
 arch/x86/cpu/intel_common/car2_uninit.S |  87 +++++
 4 files changed, 601 insertions(+)
 create mode 100644 arch/x86/cpu/intel_common/car2.S
 create mode 100644 arch/x86/cpu/intel_common/car2_uninit.S

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 54f51e002b8..69327bd746a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -889,4 +889,20 @@ config HIGH_TABLE_SIZE
 	  Increse it if the default size does not fit the board's needs.
 	  This is most likely due to a large ACPI DSDT table is used.
 
+config INTEL_CAR_CQOS
+	bool "Support Intel Cache Quality of Service"
+	help
+	  Cache Quality of Service allows more fine-grained control of cache
+	  usage. As result, it is possible to set up a portion of L2 cache for
+	  CAR and use the remainder for actual caching.
+
+#
+# Each bit in QOS mask controls this many bytes. This is calculated as:
+# (CACHE_WAYS / CACHE_BITS_PER_MASK) * CACHE_LINE_SIZE * CACHE_SETS
+#
+config CACHE_QOS_SIZE_PER_BIT
+	hex
+	depends on INTEL_CAR_CQOS
+	default 0x20000 # 128 KB
+
 endmenu
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile
index dfbc29f0475..4c733f46067 100644
--- a/arch/x86/cpu/intel_common/Makefile
+++ b/arch/x86/cpu/intel_common/Makefile
@@ -8,6 +8,14 @@ obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
 obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
 obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
 endif
+
+ifdef CONFIG_FSP_VERSION2
+obj-$(CONFIG_TPL_BUILD) += car2.o
+ifndef CONFIG_SPL_BUILD
+obj-y += car2_uninit.o
+endif
+endif
+
 obj-y += cpu.o
 obj-y += fast_spi.o
 obj-y += lpc.o
diff --git a/arch/x86/cpu/intel_common/car2.S b/arch/x86/cpu/intel_common/car2.S
new file mode 100644
index 00000000000..bf01b0da849
--- /dev/null
+++ b/arch/x86/cpu/intel_common/car2.S
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <config.h>
+#include <asm/msr-index.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/processor-flags.h>
+
+#define KiB 1024
+
+.global car_init
+car_init:
+	post_code(0x20)
+
+	/*
+	 * Use the MTRR default type MSR as a proxy for detecting INIT#.
+	 * Reset the system if any known bits are set in that MSR. That is
+	 * an indication of the CPU not being properly reset.
+	 */
+check_for_clean_reset:
+	mov	$MTRR_DEF_TYPE_MSR, %ecx
+	rdmsr
+	and	$(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax
+	cmp	$0, %eax
+	jz	no_reset
+	/* perform warm reset */
+	movw	$0xcf9, %dx
+	movb	$0x06, %al
+	outb	%al, %dx
+
+no_reset:
+	post_code(0x21)
+
+	/* Clear/disable fixed MTRRs */
+	mov	$fixed_mtrr_list_size, %ebx
+	xor	%eax, %eax
+	xor	%edx, %edx
+
+clear_fixed_mtrr:
+	add	$-2, %ebx
+	movzwl	fixed_mtrr_list(%ebx), %ecx
+	wrmsr
+	jnz	clear_fixed_mtrr
+
+	post_code(0x22)
+
+	/* Figure put how many MTRRs we have, and clear them out */
+	mov	$MTRR_CAP_MSR, %ecx
+	rdmsr
+	movzb	%al, %ebx		/* Number of variable MTRRs */
+	mov	$MTRR_PHYS_BASE_MSR(0), %ecx
+	xor	%eax, %eax
+	xor	%edx, %edx
+
+clear_var_mtrr:
+	wrmsr
+	inc	%ecx
+	wrmsr
+	inc	%ecx
+	dec	%ebx
+	jnz	clear_var_mtrr
+
+	post_code(0x23)
+
+	/* Configure default memory type to uncacheable (UC) */
+	mov	$MTRR_DEF_TYPE_MSR, %ecx
+	rdmsr
+	/* Clear enable bits and set default type to UC */
+	and	$~(MTRR_DEF_TYPE_MASK | MTRR_DEF_TYPE_EN | \
+		 MTRR_DEF_TYPE_FIX_EN), %eax
+	wrmsr
+
+	/* Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
+	 * based on the physical address size supported for this processor
+	 * This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
+	 *
+	 * Examples:
+	 *  MTRR_PHYS_MASK_HIGH = 00000000Fh  For 36 bit addressing
+	 *  MTRR_PHYS_MASK_HIGH = 0000000FFh  For 40 bit addressing
+	 */
+
+	movl	$0x80000008, %eax 	/* Address sizes leaf */
+	cpuid
+	sub	$32, %al
+	movzx	%al, %eax
+	xorl	%esi, %esi
+	bts	%eax, %esi
+	dec	%esi			/* esi <- MTRR_PHYS_MASK_HIGH */
+
+	post_code(0x24)
+
+#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)
+	/* Configure CAR region as write-back (WB) */
+	mov	$MTRR_PHYS_BASE_MSR(0), %ecx
+	mov	$CONFIG_DCACHE_RAM_BASE, %eax
+	or	$MTRR_TYPE_WRBACK, %eax
+	xor	%edx,%edx
+	wrmsr
+
+	/* Configure the MTRR mask for the size region */
+	mov	$MTRR_PHYS_MASK(0), %ecx
+	mov	$CONFIG_DCACHE_RAM_SIZE, %eax	/* size mask */
+	dec	%eax
+	not	%eax
+	or	$MTRR_PHYS_MASK_VALID, %eax
+	movl	%esi, %edx	/* edx <- MTRR_PHYS_MASK_HIGH */
+	wrmsr
+#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
+	/* Configure CAR region as write-back (WB) */
+	mov	$MTRR_PHYS_BASE_MSR(0), %ecx
+	mov	$CONFIG_DCACHE_RAM_BASE, %eax
+	or	$MTRR_TYPE_WRBACK, %eax
+	xor	%edx,%edx
+	wrmsr
+
+	mov	$MTRR_PHYS_MASK_MSR(0), %ecx
+	mov	$(512 * KiB), %eax	/* size mask */
+	dec	%eax
+	not	%eax
+	or	$MTRR_PHYS_MASK_VALID, %eax
+	movl	%esi, %edx	/* edx <- MTRR_PHYS_MASK_HIGH */
+	wrmsr
+
+	mov	$MTRR_PHYS_BASE_MSR(1), %ecx
+	mov	$(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
+	or	$MTRR_TYPE_WRBACK, %eax
+	xor	%edx,%edx
+	wrmsr
+
+	mov	$MTRR_PHYS_MASK_MSR(1), %ecx
+	mov	$(256 * KiB), %eax	/* size mask */
+	dec	%eax
+	not	%eax
+	or	$MTRR_PHYS_MASK_VALID, %eax
+	movl	%esi, %edx	/* edx <- MTRR_PHYS_MASK_HIGH */
+	wrmsr
+#else
+#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
+#endif
+	post_code(0x25)
+
+	/* start */
+/* 	mov	$0xffff80a8, %ebx */
+/* 	jmp	*%ebx */
+.globl _from_bb
+_from_bb:
+/* 	jmp	car_init_ret */
+	/* end */
+
+	/* Enable variable MTRRs */
+	mov	$MTRR_DEF_TYPE_MSR, %ecx
+	rdmsr
+	or	$MTRR_DEF_TYPE_EN, %eax
+	wrmsr
+
+	/* Enable caching */
+	mov	%cr0, %eax
+	and	$~(X86_CR0_CD | X86_CR0_NW), %eax
+	invd
+	mov	%eax, %cr0
+
+#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
+	jmp car_nem
+#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
+	jmp car_cqos
+#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
+	jmp car_nem_enhanced
+#else
+#error "No CAR mechanism selected:
+#endif
+	jmp	car_init_ret
+
+#if 0
+.global car_init_done
+car_init_done:
+
+	post_code(0x29)
+
+	/* Setup bootblock stack */
+	mov	$_car_stack_end, %esp
+
+	/* Need to align stack to 16 bytes@call instruction. Account for
+	   the two pushes below */
+	andl	$0xfffffff0, %esp
+	sub	$8, %esp
+
+	/*push TSC value to stack*/
+	movd	%mm2, %eax
+	pushl	%eax	/* tsc[63:32] */
+	movd	%mm1, %eax
+	pushl	%eax 	/* tsc[31:0] */
+
+before_carstage:
+	post_code(0x2A)
+
+	call	bootblock_c_entry
+	/* Never reached */
+#endif
+
+fixed_mtrr_list:
+	.word	MTRR_FIX_64K_00000_MSR
+	.word	MTRR_FIX_16K_80000_MSR
+	.word	MTRR_FIX_16K_A0000_MSR
+	.word	MTRR_FIX_4K_C0000_MSR
+	.word	MTRR_FIX_4K_C8000_MSR
+	.word	MTRR_FIX_4K_D0000_MSR
+	.word	MTRR_FIX_4K_D8000_MSR
+	.word	MTRR_FIX_4K_E0000_MSR
+	.word	MTRR_FIX_4K_E8000_MSR
+	.word	MTRR_FIX_4K_F0000_MSR
+	.word	MTRR_FIX_4K_F8000_MSR
+fixed_mtrr_list_size = . - fixed_mtrr_list
+
+#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
+.global car_nem
+car_nem:
+	/* Disable cache eviction (setup stage) */
+	mov	$MSR_EVICT_CTL, %ecx
+	rdmsr
+	or	$0x1, %eax
+	wrmsr
+
+	post_code(0x26)
+
+	/* Clear the cache memory region. This will also fill up the cache */
+	movl	$CONFIG_DCACHE_RAM_BASE, %edi
+	movl	$CONFIG_DCACHE_RAM_SIZE, %ecx
+	shr	$0x02, %ecx
+	xor	%eax, %eax
+	cld
+	rep	stosl
+
+	post_code(0x27)
+
+	/* Disable cache eviction (run stage) */
+	mov	$MSR_EVICT_CTL, %ecx
+	rdmsr
+	or	$0x2, %eax
+	wrmsr
+
+	post_code(0x28)
+
+	jmp car_init_done
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
+.global car_cqos
+car_cqos:
+	/*
+	 * Create CBM_LEN_MASK based on CBM_LEN
+	 * Get CPUID.(EAX=10H, ECX=2H):EAX.CBM_LEN[bits 4:0]
+	 */
+	mov $0x10, %eax
+	mov $0x2,  %ecx
+	cpuid
+	and $0x1F, %eax
+	add $1, %al
+
+	mov $1, %ebx
+	mov %al, %cl
+	shl %cl, %ebx
+	sub $1, %ebx
+
+	/* Store the CBM_LEN_MASK in mm3 for later use */
+	movd %ebx, %mm3
+
+	/*
+	 * Disable both L1 and L2 prefetcher. For yet-to-understood reason,
+	 * prefetchers slow down filling cache with rep stos in CQOS mode.
+	 */
+	mov	$MSR_PREFETCH_CTL, %ecx
+	rdmsr
+	or	$(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
+	wrmsr
+
+#if (CONFIG_DCACHE_RAM_SIZE == CONFIG_L2_CACHE_SIZE)
+/*
+ * If CAR size is set to full L2 size, mask is calculated as all-zeros.
+ * This is not supported by the CPU/uCode.
+ */
+#error "CQOS CAR may not use whole L2 cache area"
+#endif
+
+	/* Calculate how many bits to be used for CAR */
+	xor	%edx, %edx
+	mov	$CONFIG_DCACHE_RAM_SIZE, %eax	/* dividend */
+	mov	$CONFIG_CACHE_QOS_SIZE_PER_BIT, %ecx	/* divisor */
+	div	%ecx		/* result is in eax */
+	mov	%eax, %ecx	/* save to ecx */
+	mov	$1, %ebx
+	shl	%cl, %ebx
+	sub	$1, %ebx	/* resulting mask is is in ebx */
+
+	/* Set this mask for initial cache fill */
+	mov	$MSR_L2_QOS_MASK(0), %ecx
+	rdmsr
+	mov	%ebx, %eax
+	wrmsr
+
+	/* Set CLOS selector to 0 */
+	mov	$MSR_IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~MSR_IA32_PQR_ASSOC_MASK, %edx	/* select mask 0 */
+	wrmsr
+
+	/* We will need to block CAR region from evicts */
+	mov	$MSR_L2_QOS_MASK(1), %ecx
+	rdmsr
+	/* Invert bits that are to be used for cache */
+	mov	%ebx, %eax
+	xor	$~0, %eax			/* invert 32 bits */
+
+	/*
+	 * Use CBM_LEN_MASK stored in mm3 to set bits based on Capacity Bit
+	 * Mask Length.
+	 */
+	movd	%mm3, %ebx
+	and	%ebx, %eax
+	wrmsr
+
+	post_code(0x26)
+
+	/* Clear the cache memory region. This will also fill up the cache */
+	movl	$CONFIG_DCACHE_RAM_BASE, %edi
+	movl	$CONFIG_DCACHE_RAM_SIZE, %ecx
+	shr	$0x02, %ecx
+	xor	%eax, %eax
+	cld
+	rep	stosl
+
+	post_code(0x27)
+
+	/* Cache is populated. Use mask 1 that will block evicts */
+	mov	$MSR_IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~MSR_IA32_PQR_ASSOC_MASK, %edx	/* clear index bits first */
+	or	$1, %edx			/* select mask 1 */
+	wrmsr
+
+	/* Enable prefetchers */
+	mov	$MSR_PREFETCH_CTL, %ecx
+	rdmsr
+	and	$~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
+	wrmsr
+
+	post_code(0x28)
+
+/* 	jmp car_init_done */
+	jmp	car_init_ret
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
+.global car_nem_enhanced
+car_nem_enhanced:
+	/* Disable cache eviction (setup stage) */
+	mov	$MSR_EVICT_CTL, %ecx
+	rdmsr
+	or	$0x1, %eax
+	wrmsr
+	post_code(0x26)
+
+	/* Create n-way set associativity of cache */
+	xorl	%edi, %edi
+find_llc_subleaf:
+	movl	%edi, %ecx
+	movl	$0x04, %eax
+	cpuid
+	inc	%edi
+	and	$0xe0, %al	/* EAX[7:5] = Cache Level */
+	cmp	$0x60, %al	/* Check to see if it is LLC */
+	jnz	find_llc_subleaf
+
+	/*
+	 * Set MSR 0xC91 IA32_L3_MASK_! = 0xE/0xFE/0xFFE/0xFFFE
+	 * for 4/8/16 way of LLC
+	*/
+	shr	$22, %ebx
+	inc	%ebx
+	/* Calculate n-way associativity of LLC */
+	mov	%bl, %cl
+
+	/*
+	 * Maximizing RO cacheability while locking in the CAR to a
+	 * single way since that particular way won't be victim candidate
+	 * for evictions.
+	 * This has been done after programing LLC_WAY_MASK_1 MSR
+	 * with desired LLC way as mentioned below.
+	 *
+	 * Hence create Code and Data Size as per request
+	 * Code Size (RO) : Up to 16M
+	 * Data Size (RW) : Up to 256K
+	 */
+	movl	$0x01, %eax
+	/*
+	 * LLC Ways -> LLC_WAY_MASK_1:
+	 *  4: 0x000E
+	 *  8: 0x00FE
+	 * 12: 0x0FFE
+	 * 16: 0xFFFE
+	 *
+	 * These MSRs contain one bit per each way of LLC
+	 * - If this bit is '0' - the way is protected from eviction
+	 * - If this bit is '1' - the way is not protected from eviction
+	 */
+	shl	%cl, %eax
+	subl	$0x02, %eax
+	movl	$MSR_IA32_L3_MASK_1, %ecx
+	xorl	%edx, %edx
+	wrmsr
+	/*
+	 * Set MSR 0xC92 IA32_L3_MASK_2 = 0x1
+	 *
+	 * For SKL SOC, data size remains 256K consistently.
+	 * Hence, creating 1-way associative cache for Data
+	*/
+	mov	$MSR_IA32_L3_MASK_2, %ecx
+	mov	$0x01, %eax
+	xorl	%edx, %edx
+	wrmsr
+	/*
+	 * Set MSR_IA32_PQR_ASSOC = 0x02
+	 *
+	 * Possible values:
+	 * 0: Default value, no way mask should be applied
+	 * 1: Apply way mask 1 to LLC
+	 * 2: Apply way mask 2 to LLC
+	 * 3: Shouldn't be use in NEM Mode
+	 */
+	movl	$MSR_IA32_PQR_ASSOC, %ecx
+	movl	$0x02, %eax
+	xorl	%edx, %edx
+	wrmsr
+
+	movl	$CONFIG_DCACHE_RAM_BASE, %edi
+	movl	$CONFIG_DCACHE_RAM_SIZE, %ecx
+	shr	$0x02, %ecx
+	xor	%eax, %eax
+	cld
+	rep	stosl
+	/*
+	 * Set MSR_IA32_PQR_ASSOC = 0x01
+	 * At this stage we apply LLC_WAY_MASK_1 to the cache.
+	 * i.e. way 0 is protected from eviction.
+	*/
+	movl	$MSR_IA32_PQR_ASSOC, %ecx
+	movl	$0x01, %eax
+	xorl	%edx, %edx
+	wrmsr
+
+	post_code(0x27)
+	/*
+	 * Enable No-Eviction Mode Run State by setting
+	 * NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
+	 */
+
+	movl	$MSR_EVICT_CTL, %ecx
+	rdmsr
+	orl	$0x02, %eax
+	wrmsr
+
+	post_code(0x28)
+
+	jmp car_init_done
+#endif
+
+#if CONFIG_IS_ENABLED(X86_16BIT_INIT)
+_dt_ucode_base_size:
+	/* These next two fields are filled in by binman */
+.globl ucode_base
+ucode_base:	/* Declared in microcode.h */
+	.long	0			/* microcode base */
+.globl ucode_size
+ucode_size:	/* Declared in microcode.h */
+	.long	0			/* microcode size */
+	.long	CONFIG_SYS_MONITOR_BASE	/* code region base */
+	.long	CONFIG_SYS_MONITOR_LEN	/* code region size */
+#endif
diff --git a/arch/x86/cpu/intel_common/car2_uninit.S b/arch/x86/cpu/intel_common/car2_uninit.S
new file mode 100644
index 00000000000..aba3a5381e5
--- /dev/null
+++ b/arch/x86/cpu/intel_common/car2_uninit.S
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2017 Intel Corp.
+ * Copyright 2019 Google LLC
+ * Taken from coreboot file exit_car.S
+ */
+
+#include <config.h>
+#include <asm/msr-index.h>
+#include <asm/mtrr.h>
+
+.text
+.global car_uninit
+car_uninit:
+
+	/*
+	 * Retrieve return address from stack as it will get trashed below if
+	 * execution is utilizing the cache-as-ram stack.
+	 */
+	pop	%ebx
+
+	/* Disable MTRRs */
+	mov	$(MTRR_DEF_TYPE_MSR), %ecx
+	rdmsr
+	and	$(~(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN)), %eax
+	wrmsr
+
+#ifdef CONFIG_INTEL_CAR_NEM
+.global car_nem_teardown
+car_nem_teardown:
+
+	/* invalidate cache contents */
+	invd
+
+	/* Knock down bit 1 then bit 0 of NEM control not combining steps */
+	mov	$(MSR_EVICT_CTL), %ecx
+	rdmsr
+	and	$(~(1 << 1)), %eax
+	wrmsr
+	and	$(~(1 << 0)), %eax
+	wrmsr
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
+.global car_cqos_teardown
+car_cqos_teardown:
+
+	/* Go back to all-evicting mode, set both masks to all-1s */
+	mov	$MSR_L2_QOS_MASK(0), %ecx
+	rdmsr
+	mov	$~0, %al
+	wrmsr
+
+	mov	$MSR_L2_QOS_MASK(1), %ecx
+	rdmsr
+	mov	$~0, %al
+	wrmsr
+
+	/* Reset CLOS selector to 0 */
+	mov	$MSR_IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~MSR_IA32_PQR_ASSOC_MASK, %edx
+	wrmsr
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
+.global car_nem_enhanced_teardown
+car_nem_enhanced_teardown:
+
+	/* invalidate cache contents */
+	invd
+
+	/* Knock down bit 1 then bit 0 of NEM control not combining steps */
+	mov	$(MSR_EVICT_CTL), %ecx
+	rdmsr
+	and	$(~(1 << 1)), %eax
+	wrmsr
+	and	$(~(1 << 0)), %eax
+	wrmsr
+
+	/* Reset CLOS selector to 0 */
+	mov	$IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~IA32_PQR_ASSOC_MASK, %edx
+	wrmsr
+#endif
+
+	/* Return to caller */
+	jmp	*%ebx
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 065/108] x86: Disable microcode section for FSP2
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (41 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:02   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 066/108] x86: Update the fsp command " Simon Glass
                   ` (44 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present we don't support loading microcode with FSP2. The correct way
to do this is by adding it to the FIT. For now, disable including
microcode in the image.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Drop unnecessary #else part of CONFIG_HAVE_MICROCODE

Changes in v2: None

 arch/x86/Kconfig         | 4 ++++
 arch/x86/dts/u-boot.dtsi | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 69327bd746a..37e94d8913a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -598,6 +598,10 @@ config HAVE_REFCODE
           broadwell) U-Boot will be missing some critical setup steps.
           Various peripherals may fail to work.
 
+config HAVE_MICROCODE
+	bool
+	default y if !FSP_VERSION2
+
 config SMP
 	bool "Enable Symmetric Multiprocessing"
 	default n
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 049f47c9ffd..aaca8874540 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -37,11 +37,13 @@
 	};
 #endif
 #ifdef CONFIG_TPL
+#ifdef CONFIG_HAVE_MICROCODE
 	u-boot-tpl-with-ucode-ptr {
 		offset = <CONFIG_TPL_TEXT_BASE>;
 	};
 	u-boot-tpl-dtb {
 	};
+#endif
 	u-boot-spl {
 		offset = <CONFIG_SPL_TEXT_BASE>;
 	};
@@ -77,11 +79,16 @@
 		offset = <CONFIG_SYS_TEXT_BASE>;
 	};
 #endif
+#ifdef CONFIG_HAVE_MICROCODE
 	u-boot-dtb-with-ucode {
 	};
 	u-boot-ucode {
 		align = <16>;
 	};
+#else
+	u-boot-dtb {
+	};
+#endif
 #ifdef CONFIG_X86_HAS_FIT
 	intel-fit {
 	};
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 066/108] x86: Update the fsp command for FSP2
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (42 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 065/108] x86: Disable microcode section for FSP2 Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:34   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 067/108] x86: Update .dtsi file " Simon Glass
                   ` (43 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

The current 'fsp' command only works with FSP1. Update it to handle FSP2
as well. Convert everything to hex which is what U-Boot uses.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Convert code to use hex increased of decimal
- Update the 'fsp' command for FSP2, instead of disabling it

Changes in v2: None

 cmd/x86/fsp.c | 59 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 20 deletions(-)

diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c
index b3b663021bc..fd5328db181 100644
--- a/cmd/x86/fsp.c
+++ b/cmd/x86/fsp.c
@@ -5,19 +5,30 @@
 
 #include <common.h>
 #include <command.h>
-#include <asm/fsp1/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	struct fsp_header *hdr = fsp_find_header();
-	u32 img_addr = hdr->img_base;
-	char *sign = (char *)&hdr->sign;
+	struct fsp_header *hdr;
+	u32 img_addr;
+	char *sign;
+	uint addr;
 	int i;
 
-	printf("FSP    : binary 0x%08x, header 0x%08x\n",
-	       CONFIG_FSP_ADDR, (int)hdr);
+#ifdef CONFIG_FSP_VERSION2
+	hdr = gd->arch.fsp_s_hdr;
+	img_addr = hdr->img_base;
+	addr = img_addr;
+#else
+	addr = CONFIG_FSP_ADDR;
+	hdr = fsp_find_header();
+	img_addr = hdr->img_base;
+#endif
+	sign = (char *)&hdr->sign;
+
+	printf("FSP    : binary %08x, header %08x\n", addr, (int)hdr);
 	printf("Header : sign ");
 	for (i = 0; i < sizeof(hdr->sign); i++)
 		printf("%c", *sign++);
@@ -34,24 +45,32 @@ static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	printf(", id ");
 	for (i = 0; i < ARRAY_SIZE(hdr->img_id); i++)
 		printf("%c", hdr->img_id[i]);
-	printf(", addr 0x%08x, size %d\n", img_addr, hdr->img_size);
-	if (hdr->hdr_rev == FSP_HEADER_REVISION_2) {
+	printf(", addr %08x, size %d\n", img_addr, hdr->img_size);
+	if (hdr->hdr_rev >= FSP_HEADER_REVISION_1) {
 		printf("GFX    :%ssupported\n",
 		       hdr->img_attr & FSP_ATTR_GRAPHICS_SUPPORT ? " " : " un");
 	}
-	printf("VPD    : addr 0x%08x, size %d\n",
+	printf("VPD    : addr %08x, size %x\n",
 	       hdr->cfg_region_off + img_addr, hdr->cfg_region_size);
-	printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
-	printf("\tTempRamInit : 0x%08x\n", hdr->fsp_tempram_init + img_addr);
-	printf("\tFspInit     : 0x%08x\n", hdr->fsp_init + img_addr);
-	printf("\tFspNotify   : 0x%08x\n", hdr->fsp_notify + img_addr);
-	if (hdr->hdr_rev == FSP_HEADER_REVISION_2) {
-		printf("\tMemoryInit  : 0x%08x\n",
-		       hdr->fsp_mem_init + img_addr);
-		printf("\tTempRamExit : 0x%08x\n",
-		       hdr->fsp_tempram_exit + img_addr);
-		printf("\tSiliconInit : 0x%08x\n",
-		       hdr->fsp_silicon_init + img_addr);
+	if (hdr->hdr_rev <= FSP_HEADER_REVISION_2)
+		printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
+	if (hdr->fsp_tempram_init)
+		printf("\tTempRamInit : %08x\n",
+		       hdr->fsp_tempram_init + img_addr);
+	if (hdr->fsp_init)
+		printf("\tFspInit     : %08x\n", hdr->fsp_init + img_addr);
+	if (hdr->fsp_notify)
+		printf("\tFspNotify   : %08x\n", hdr->fsp_notify + img_addr);
+	if (hdr->hdr_rev >= FSP_HEADER_REVISION_1) {
+		if (hdr->fsp_mem_init)
+			printf("\tMemoryInit  : %08x\n",
+			       hdr->fsp_mem_init + img_addr);
+		if (hdr->fsp_tempram_exit)
+			printf("\tTempRamExit : %08x\n",
+			       hdr->fsp_tempram_exit + img_addr);
+		if (hdr->fsp_silicon_init)
+			printf("\tSiliconInit : %08x\n",
+			       hdr->fsp_silicon_init + img_addr);
 	}
 
 	return 0;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 067/108] x86: Update .dtsi file for FSP2
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (43 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 066/108] x86: Update the fsp command " Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:34   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot Simon Glass
                   ` (42 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Include the IFWI section and the FSP-M binary. The FSP-T binary is not
currently used, as CAR is set up manually.

Also drop the FSP binary as this relates only to FSP1.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add FSP-S and VBT also

Changes in v2: None

 arch/x86/dts/u-boot.dtsi | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index aaca8874540..51d003dcfe1 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -100,12 +100,45 @@
 		offset = <CONFIG_X86_MRC_ADDR>;
 	};
 #endif
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_FSP_VERSION1
 	intel-fsp {
 		filename = CONFIG_FSP_FILE;
 		offset = <CONFIG_FSP_ADDR>;
 	};
 #endif
+#ifdef CONFIG_FSP_VERSION2
+	intel-descriptor {
+		filename = CONFIG_FLASH_DESCRIPTOR_FILE;
+	};
+	intel-ifwi {
+		filename = CONFIG_IFWI_INPUT_FILE;
+		convert-fit;
+
+		section {
+			size = <0x8000>;
+			ifwi-replace;
+			ifwi-subpart = "IBBP";
+			ifwi-entry = "IBBL";
+			u-boot-tpl {
+			};
+			x86-start16-tpl {
+				offset = <0x7800>;
+			};
+			x86-reset16-tpl {
+				offset = <0x7ff0>;
+			};
+		};
+	};
+	intel-fsp-m {
+		filename = CONFIG_FSP_FILE_M;
+	};
+	intel-fsp-s {
+		filename = CONFIG_FSP_FILE_S;
+	};
+	intel-vbt {
+		filename = CONFIG_FSP_FILE_VBT;
+	};
+#endif
 #ifdef CONFIG_HAVE_CMC
 	intel-cmc {
 		filename = CONFIG_CMC_FILE;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (44 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 067/108] x86: Update .dtsi file " Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:34   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 069/108] x86: Add an option to control the position of SPL Simon Glass
                   ` (41 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

The existing work-around for positioning U-Boot in the ROM when it
actually runs from RAM still exists and there is not obvious way to change
this.

Add a proper Kconfig option to handle this case. This also adds a new bool
property to indicate whether CONFIG_SYS_TEXT_BASE exists.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 Kconfig                                |  9 ++++++---
 arch/x86/Kconfig                       |  5 +++++
 arch/x86/dts/u-boot.dtsi               | 18 +++---------------
 configs/chromebook_samus_tpl_defconfig |  1 +
 4 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/Kconfig b/Kconfig
index 66b059f749a..86161b662de 100644
--- a/Kconfig
+++ b/Kconfig
@@ -530,9 +530,14 @@ config SYS_EXTRA_OPTIONS
 	  configuration to Kconfig. Since this option will be removed sometime,
 	  new boards should not use this option.
 
-config SYS_TEXT_BASE
+config HAS_SYS_TEXT_BASE
+	bool
 	depends on !NIOS2 && !XTENSA
 	depends on !EFI_APP
+	default y
+
+config SYS_TEXT_BASE
+	depends on HAS_SYS_TEXT_BASE
 	default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3
 	default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S
 	default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I
@@ -541,8 +546,6 @@ config SYS_TEXT_BASE
 	help
 	  The address in memory that U-Boot will be running from, initially.
 
-
-
 config SYS_CLK_FREQ
 	depends on ARC || ARCH_SUNXI || MPC83xx
 	int "CPU clock frequency"
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 37e94d8913a..f015e380f90 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -909,4 +909,9 @@ config CACHE_QOS_SIZE_PER_BIT
 	depends on INTEL_CAR_CQOS
 	default 0x20000 # 128 KB
 
+config X86_OFFSET_U_BOOT
+	hex "Offset of U-Boot in ROM image"
+	depends on HAS_SYS_TEXT_BASE
+	default SYS_TEXT_BASE
+
 endmenu
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 51d003dcfe1..66c4fdc8f8a 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -50,7 +50,7 @@
 	u-boot-spl-dtb {
 	};
 	u-boot {
-		offset = <CONFIG_SYS_TEXT_BASE>;
+		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
 #elif defined(CONFIG_SPL)
 	u-boot-spl-with-ucode-ptr {
@@ -60,23 +60,11 @@
 		type = "u-boot-dtb-with-ucode";
 	};
 	u-boot {
-		/*
-		 * TODO(sjg at chromium.org):
-		 * Normally we use CONFIG_SYS_TEXT_BASE as the flash offset. But
-		 * for boards with textbase in SDRAM we cannot do this. Just use
-		 * an assumed-valid value (1MB before the end of flash) here so
-		 * that we can actually build an image for coreboot, etc.
-		 * We need a better solution, perhaps a separate Kconfig.
-		 */
-#if CONFIG_SYS_TEXT_BASE == 0x1110000
-		offset = <0xfff00000>;
-#else
-		offset = <CONFIG_SYS_TEXT_BASE>;
-#endif
+		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
 #else
 	u-boot-with-ucode-ptr {
-		offset = <CONFIG_SYS_TEXT_BASE>;
+		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
 #endif
 #ifdef CONFIG_HAVE_MICROCODE
diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig
index 28f23cfe125..c7f125eaa40 100644
--- a/configs/chromebook_samus_tpl_defconfig
+++ b/configs/chromebook_samus_tpl_defconfig
@@ -13,6 +13,7 @@ CONFIG_HAVE_REFCODE=y
 CONFIG_SMP=y
 CONFIG_HAVE_VGA_BIOS=y
 CONFIG_SPL_TEXT_BASE=0xffe70000
+CONFIG_X86_OFFSET_U_BOOT=0xfff00000
 CONFIG_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_SHOW_BOOT_PROGRESS=y
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 069/108] x86: Add an option to control the position of SPL
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (45 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:34   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 070/108] x86: Add an fdtmap and image-header Simon Glass
                   ` (40 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

For apollolake SPL is run from CAR (cache-as-RAM) which is in a different
location from where SPL must be placed in ROM. In other words, although
SPL runs before SDRAM is set up, it is not execute-in-place (XIP).

Add a Kconfig option for the ROM position.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add SPL condition to the option

Changes in v2: None

 arch/x86/Kconfig         | 5 +++++
 arch/x86/dts/u-boot.dtsi | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index f015e380f90..c9f1b6d8ada 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -914,4 +914,9 @@ config X86_OFFSET_U_BOOT
 	depends on HAS_SYS_TEXT_BASE
 	default SYS_TEXT_BASE
 
+config X86_OFFSET_SPL
+	hex "Offset of SPL in ROM image"
+	depends on SPL && X86
+	default SPL_TEXT_BASE
+
 endmenu
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 66c4fdc8f8a..a8b57e78ead 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -45,7 +45,7 @@
 	};
 #endif
 	u-boot-spl {
-		offset = <CONFIG_SPL_TEXT_BASE>;
+		offset = <CONFIG_X86_OFFSET_SPL>;
 	};
 	u-boot-spl-dtb {
 	};
@@ -54,7 +54,7 @@
 	};
 #elif defined(CONFIG_SPL)
 	u-boot-spl-with-ucode-ptr {
-		offset = <CONFIG_SPL_TEXT_BASE>;
+		offset = <CONFIG_X86_OFFSET_SPL>;
 	};
 	u-boot-dtb-with-ucode2 {
 		type = "u-boot-dtb-with-ucode";
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 070/108] x86: Add an fdtmap and image-header
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (46 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 069/108] x86: Add an option to control the position of SPL Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19  8:34   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 071/108] x86: Don't repeat microcode in U-Boot if not needed Simon Glass
                   ` (39 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add these entries to the ROM so that we can list the contents of an image
with 'binman ls'. The image-header is not essential but does speed up
access.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/dts/u-boot.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index a8b57e78ead..9796f4776a3 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -127,6 +127,8 @@
 		filename = CONFIG_FSP_FILE_VBT;
 	};
 #endif
+	fdtmap {
+	};
 #ifdef CONFIG_HAVE_CMC
 	intel-cmc {
 		filename = CONFIG_CMC_FILE;
@@ -172,5 +174,8 @@
 		offset = <CONFIG_RESET_VEC_LOC>;
 	};
 #endif
+	image-header {
+		location = "end";
+	};
 };
 #endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 071/108] x86: Don't repeat microcode in U-Boot if not needed
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (47 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 070/108] x86: Add an fdtmap and image-header Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:33   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 072/108] x86: Separate out U-Boot and device tree in ROM image Simon Glass
                   ` (38 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present if SPL sets up the microcode then it is still included in
U-Boot as well. This is wasteful as microcode is large. Adjust the logic
in the image to prevent this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/dts/u-boot.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 9796f4776a3..bb61b6e8af1 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -63,9 +63,16 @@
 		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
 #else
+# ifdef CONFIG_SPL
+	u-boot {
+		offset = <CONFIG_SYS_TEXT_BASE>;
+	};
+# else
+	/* If there is no SPL then we need to put microcode in U-Boot */
 	u-boot-with-ucode-ptr {
 		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
+# endif
 #endif
 #ifdef CONFIG_HAVE_MICROCODE
 	u-boot-dtb-with-ucode {
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 072/108] x86: Separate out U-Boot and device tree in ROM image
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (48 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 071/108] x86: Don't repeat microcode in U-Boot if not needed Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:33   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 073/108] x86: Make MSR_PKG_POWER_SKU common Simon Glass
                   ` (37 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present binman does not support updating a device tree that is part of
U-Boot (i.e u-boot.bin). Separate the entries into two so that we can get
updated entry information. This makes binman_entry_find() work correctly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/dts/u-boot.dtsi | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index bb61b6e8af1..0f3690e8188 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -49,9 +49,11 @@
 	};
 	u-boot-spl-dtb {
 	};
-	u-boot {
+	u-boot-nodtb {
 		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
+	u-boot-dtb {
+	};
 #elif defined(CONFIG_SPL)
 	u-boot-spl-with-ucode-ptr {
 		offset = <CONFIG_X86_OFFSET_SPL>;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 073/108] x86: Make MSR_PKG_POWER_SKU common
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (49 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 072/108] x86: Separate out U-Boot and device tree in ROM image Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:33   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 074/108] spi: Correct operations check in dm_spi_xfer() Simon Glass
                   ` (36 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

This is used on several boards so add it to the common file. Also add a
useful power-limit value while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/arch-broadwell/cpu.h         | 1 -
 arch/x86/include/asm/arch-ivybridge/model_206ax.h | 1 -
 arch/x86/include/asm/msr-index.h                  | 9 ++++++++-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/arch-broadwell/cpu.h b/arch/x86/include/asm/arch-broadwell/cpu.h
index 3bc3bd6609e..2b39a76fbdb 100644
--- a/arch/x86/include/asm/arch-broadwell/cpu.h
+++ b/arch/x86/include/asm/arch-broadwell/cpu.h
@@ -27,7 +27,6 @@
 
 #define MSR_VR_CURRENT_CONFIG		0x601
 #define MSR_VR_MISC_CONFIG		0x603
-#define MSR_PKG_POWER_SKU		0x614
 #define MSR_DDR_RAPL_LIMIT		0x618
 #define MSR_VR_MISC_CONFIG2		0x636
 
diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
index 4839ebc3124..5c066294bc2 100644
--- a/arch/x86/include/asm/arch-ivybridge/model_206ax.h
+++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
@@ -43,7 +43,6 @@
 #define MSR_PP1_CURRENT_CONFIG		0x602
 #define  PP1_CURRENT_LIMIT_SNB		(35 << 3) /* 35 A */
 #define  PP1_CURRENT_LIMIT_IVB		(50 << 3) /* 50 A */
-#define MSR_PKG_POWER_SKU		0x614
 
 #define IVB_CONFIG_TDP_MIN_CPUID	0x306a2
 #define MSR_CONFIG_TDP_LEVEL1		0x649
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 5bc8b6c22c7..79a9369de11 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -241,10 +241,17 @@
 #define  PKG_POWER_LIMIT_CLAMP		(1 << 16)
 #define  PKG_POWER_LIMIT_TIME_SHIFT	17
 #define  PKG_POWER_LIMIT_TIME_MASK	0x7f
+/*
+ * For Mobile, RAPL default PL1 time window value set to 28 seconds.
+ * RAPL time window calculation defined as follows:
+ * Time Window = (float)((1+X/4)*(2*^Y), X Corresponds to [23:22],
+ * Y to [21:17] in MSR 0x610. 28 sec is equal to 0x6e.
+ */
+#define  MB_POWER_LIMIT1_TIME_DEFAULT	0x6e
 
 #define MSR_PKG_ENERGY_STATUS		0x00000611
 #define MSR_PKG_PERF_STATUS		0x00000613
-#define MSR_PKG_POWER_INFO		0x00000614
+#define MSR_PKG_POWER_SKU		0x614
 
 #define MSR_DRAM_POWER_LIMIT		0x00000618
 #define MSR_DRAM_ENERGY_STATUS		0x00000619
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 074/108] spi: Correct operations check in dm_spi_xfer()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (50 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 073/108] x86: Make MSR_PKG_POWER_SKU common Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:33   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default Simon Glass
                   ` (35 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

At present we have to have an xfer() method even if it does nothing. This
is not correct, so fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c        | 9 +--------
 drivers/spi/spi-uclass.c | 5 ++++-
 include/spi.h            | 2 +-
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index fbb58c783ec..a4e4ad55c69 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -493,13 +493,6 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
 	return 0;
 }
 
-static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
-			const void *dout, void *din, unsigned long flags)
-{
-	printf("ICH SPI: Only supports memory operations\n");
-	return -1;
-}
-
 static int ich_spi_probe(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
@@ -612,7 +605,7 @@ static const struct spi_controller_mem_ops ich_controller_mem_ops = {
 };
 
 static const struct dm_spi_ops ich_spi_ops = {
-	.xfer		= ich_spi_xfer,
+	/* xfer is not supported */
 	.set_speed	= ich_spi_set_speed,
 	.set_mode	= ich_spi_set_mode,
 	.mem_ops	= &ich_controller_mem_ops,
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 9f5ff2a31d1..7535d547f25 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -85,11 +85,14 @@ int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		const void *dout, void *din, unsigned long flags)
 {
 	struct udevice *bus = dev->parent;
+	struct dm_spi_ops *ops = spi_get_ops(bus);
 
 	if (bus->uclass->uc_drv->id != UCLASS_SPI)
 		return -EOPNOTSUPP;
+	if (!ops->xfer)
+		return -ENOSYS;
 
-	return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
+	return ops->xfer(dev, bitlen, dout, din, flags);
 }
 
 int dm_spi_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
diff --git a/include/spi.h b/include/spi.h
index a12727e6361..9f005d5efe8 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -224,7 +224,7 @@ void spi_release_bus(struct spi_slave *slave);
 int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen);
 
 /**
- * SPI transfer
+ * SPI transfer (optional if mem_ops is used)
  *
  * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
  * "bitlen" bits in the SPI MISO port.  That's just the way SPI works.
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (51 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 074/108] spi: Correct operations check in dm_spi_xfer() Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:33   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 076/108] spi: ich: Move init function just above probe() Simon Glass
                   ` (34 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

We don't normally need this on x86 unless the size of SPI flash devices is
larger than 16MB. This can be enabled by particular SoCs as needed, since
it adds to code size.

Drop the default enabling of this option on x86.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b8ca2bdedd5..320baeeb3eb 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -125,7 +125,6 @@ config FSL_DSPI
 
 config ICH_SPI
 	bool "Intel ICH SPI driver"
-	imply SPI_FLASH_BAR
 	help
 	  Enable the Intel ICH SPI driver. This driver can be used to
 	  access the SPI NOR flash on platforms embedding this Intel
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 076/108] spi: ich: Move init function just above probe()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (52 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:52   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function Simon Glass
                   ` (33 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

It is annoying to have some of the init code in a different part of the
file. Move ich_init_controller() to just above probe() to keep things
together.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 122 +++++++++++++++++++++++-----------------------
 1 file changed, 61 insertions(+), 61 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index a4e4ad55c69..3eb4599ba27 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -112,67 +112,6 @@ static int ich9_can_do_33mhz(struct udevice *dev)
 	return speed == 1;
 }
 
-static int ich_init_controller(struct udevice *dev,
-			       struct ich_spi_platdata *plat,
-			       struct ich_spi_priv *ctlr)
-{
-	ulong sbase_addr;
-	void *sbase;
-
-	/* SBASE is similar */
-	pch_get_spi_base(dev->parent, &sbase_addr);
-	sbase = (void *)sbase_addr;
-	debug("%s: sbase=%p\n", __func__, sbase);
-
-	if (plat->ich_version == ICHV_7) {
-		struct ich7_spi_regs *ich7_spi = sbase;
-
-		ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
-		ctlr->menubytes = sizeof(ich7_spi->opmenu);
-		ctlr->optype = offsetof(struct ich7_spi_regs, optype);
-		ctlr->addr = offsetof(struct ich7_spi_regs, spia);
-		ctlr->data = offsetof(struct ich7_spi_regs, spid);
-		ctlr->databytes = sizeof(ich7_spi->spid);
-		ctlr->status = offsetof(struct ich7_spi_regs, spis);
-		ctlr->control = offsetof(struct ich7_spi_regs, spic);
-		ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
-		ctlr->preop = offsetof(struct ich7_spi_regs, preop);
-		ctlr->base = ich7_spi;
-	} else if (plat->ich_version == ICHV_9) {
-		struct ich9_spi_regs *ich9_spi = sbase;
-
-		ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
-		ctlr->menubytes = sizeof(ich9_spi->opmenu);
-		ctlr->optype = offsetof(struct ich9_spi_regs, optype);
-		ctlr->addr = offsetof(struct ich9_spi_regs, faddr);
-		ctlr->data = offsetof(struct ich9_spi_regs, fdata);
-		ctlr->databytes = sizeof(ich9_spi->fdata);
-		ctlr->status = offsetof(struct ich9_spi_regs, ssfs);
-		ctlr->control = offsetof(struct ich9_spi_regs, ssfc);
-		ctlr->speed = ctlr->control + 2;
-		ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
-		ctlr->preop = offsetof(struct ich9_spi_regs, preop);
-		ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
-		ctlr->pr = &ich9_spi->pr[0];
-		ctlr->base = ich9_spi;
-	} else {
-		debug("ICH SPI: Unrecognised ICH version %d\n",
-		      plat->ich_version);
-		return -EINVAL;
-	}
-
-	/* Work out the maximum speed we can support */
-	ctlr->max_speed = 20000000;
-	if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
-		ctlr->max_speed = 33000000;
-	debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
-	      plat->ich_version, ctlr->base, ctlr->max_speed);
-
-	ich_set_bbar(ctlr, 0);
-
-	return 0;
-}
-
 static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase)
 {
 	if (plat->ich_version == ICHV_7) {
@@ -493,6 +432,67 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
 	return 0;
 }
 
+static int ich_init_controller(struct udevice *dev,
+			       struct ich_spi_platdata *plat,
+			       struct ich_spi_priv *ctlr)
+{
+	ulong sbase_addr;
+	void *sbase;
+
+	/* SBASE is similar */
+	pch_get_spi_base(dev->parent, &sbase_addr);
+	sbase = (void *)sbase_addr;
+	debug("%s: sbase=%p\n", __func__, sbase);
+
+	if (plat->ich_version == ICHV_7) {
+		struct ich7_spi_regs *ich7_spi = sbase;
+
+		ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
+		ctlr->menubytes = sizeof(ich7_spi->opmenu);
+		ctlr->optype = offsetof(struct ich7_spi_regs, optype);
+		ctlr->addr = offsetof(struct ich7_spi_regs, spia);
+		ctlr->data = offsetof(struct ich7_spi_regs, spid);
+		ctlr->databytes = sizeof(ich7_spi->spid);
+		ctlr->status = offsetof(struct ich7_spi_regs, spis);
+		ctlr->control = offsetof(struct ich7_spi_regs, spic);
+		ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
+		ctlr->preop = offsetof(struct ich7_spi_regs, preop);
+		ctlr->base = ich7_spi;
+	} else if (plat->ich_version == ICHV_9) {
+		struct ich9_spi_regs *ich9_spi = sbase;
+
+		ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
+		ctlr->menubytes = sizeof(ich9_spi->opmenu);
+		ctlr->optype = offsetof(struct ich9_spi_regs, optype);
+		ctlr->addr = offsetof(struct ich9_spi_regs, faddr);
+		ctlr->data = offsetof(struct ich9_spi_regs, fdata);
+		ctlr->databytes = sizeof(ich9_spi->fdata);
+		ctlr->status = offsetof(struct ich9_spi_regs, ssfs);
+		ctlr->control = offsetof(struct ich9_spi_regs, ssfc);
+		ctlr->speed = ctlr->control + 2;
+		ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
+		ctlr->preop = offsetof(struct ich9_spi_regs, preop);
+		ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
+		ctlr->pr = &ich9_spi->pr[0];
+		ctlr->base = ich9_spi;
+	} else {
+		debug("ICH SPI: Unrecognised ICH version %d\n",
+		      plat->ich_version);
+		return -EINVAL;
+	}
+
+	/* Work out the maximum speed we can support */
+	ctlr->max_speed = 20000000;
+	if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
+		ctlr->max_speed = 33000000;
+	debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
+	      plat->ich_version, ctlr->base, ctlr->max_speed);
+
+	ich_set_bbar(ctlr, 0);
+
+	return 0;
+}
+
 static int ich_spi_probe(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (53 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 076/108] spi: ich: Move init function just above probe() Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:53   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 078/108] spi: ich: Convert to livetree Simon Glass
                   ` (32 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Reduce the size of the probe function but putting this code into its own
function.

Also remove the assumption that the PCH is always a parent of the SPI
controller, as this is not the case APL platforms. Use driver model to
find the PCH instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 55 +++++++++++++++++++++++++++++++----------------
 drivers/spi/ich.h |  1 +
 2 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 3eb4599ba27..5b3b3818ded 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -432,6 +432,37 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
 	return 0;
 }
 
+static int ich_protect_lockdown(struct udevice *dev)
+{
+	struct ich_spi_platdata *plat = dev_get_platdata(dev);
+	struct ich_spi_priv *priv = dev_get_priv(dev);
+	int ret = -ENOSYS;
+
+	/* Disable the BIOS write protect so write commands are allowed */
+	if (priv->pch)
+		ret = pch_set_spi_protect(priv->pch, false);
+	if (ret == -ENOSYS) {
+		u8 bios_cntl;
+
+		bios_cntl = ich_readb(priv, priv->bcr);
+		bios_cntl &= ~BIT(5);	/* clear Enable InSMM_STS (EISS) */
+		bios_cntl |= 1;		/* Write Protect Disable (WPD) */
+		ich_writeb(priv, bios_cntl, priv->bcr);
+	} else if (ret) {
+		debug("%s: Failed to disable write-protect: err=%d\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	/* Lock down SPI controller settings if required */
+	if (plat->lockdown) {
+		ich_spi_config_opcode(dev);
+		spi_lock_down(plat, priv->base);
+	}
+
+	return 0;
+}
+
 static int ich_init_controller(struct udevice *dev,
 			       struct ich_spi_platdata *plat,
 			       struct ich_spi_priv *ctlr)
@@ -497,30 +528,18 @@ static int ich_spi_probe(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
 	struct ich_spi_priv *priv = dev_get_priv(dev);
-	uint8_t bios_cntl;
 	int ret;
 
+	/* Find a PCH if there is one */
+	uclass_first_device(UCLASS_PCH, &priv->pch);
+
 	ret = ich_init_controller(dev, plat, priv);
 	if (ret)
 		return ret;
-	/* Disable the BIOS write protect so write commands are allowed */
-	ret = pch_set_spi_protect(dev->parent, false);
-	if (ret == -ENOSYS) {
-		bios_cntl = ich_readb(priv, priv->bcr);
-		bios_cntl &= ~BIT(5);	/* clear Enable InSMM_STS (EISS) */
-		bios_cntl |= 1;		/* Write Protect Disable (WPD) */
-		ich_writeb(priv, bios_cntl, priv->bcr);
-	} else if (ret) {
-		debug("%s: Failed to disable write-protect: err=%d\n",
-		      __func__, ret);
-		return ret;
-	}
 
-	/* Lock down SPI controller settings if required */
-	if (plat->lockdown) {
-		ich_spi_config_opcode(dev);
-		spi_lock_down(plat, priv->base);
-	}
+	ret = ich_protect_lockdown(dev);
+	if (ret)
+		return ret;
 
 	priv->cur_speed = priv->max_speed;
 
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index 3dfb2aaff15..77057878a5d 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -191,6 +191,7 @@ struct ich_spi_priv {
 	ulong max_speed;	/* Maximum bus speed in MHz */
 	ulong cur_speed;	/* Current bus speed */
 	struct spi_trans trans;	/* current transaction in progress */
+	struct udevice *pch;	/* PCH, used to control SPI access */
 };
 
 #endif /* _ICH_H_ */
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 078/108] spi: ich: Convert to livetree
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (54 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:53   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 079/108] spi: ich: Fix header order Simon Glass
                   ` (31 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Use dev_get_driver_data() to obtain the device type. It has the same
effect and is shorter.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 22 +++++-----------------
 1 file changed, 5 insertions(+), 17 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 5b3b3818ded..7c29369a169 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -598,23 +598,11 @@ static int ich_spi_child_pre_probe(struct udevice *dev)
 static int ich_spi_ofdata_to_platdata(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
-	int node = dev_of_offset(dev);
-	int ret;
 
-	ret = fdt_node_check_compatible(gd->fdt_blob, node, "intel,ich7-spi");
-	if (ret == 0) {
-		plat->ich_version = ICHV_7;
-	} else {
-		ret = fdt_node_check_compatible(gd->fdt_blob, node,
-						"intel,ich9-spi");
-		if (ret == 0)
-			plat->ich_version = ICHV_9;
-	}
+	plat->ich_version = dev_get_driver_data(dev);
+	plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
 
-	plat->lockdown = fdtdec_get_bool(gd->fdt_blob, node,
-					 "intel,spi-lock-down");
-
-	return ret;
+	return 0;
 }
 
 static const struct spi_controller_mem_ops ich_controller_mem_ops = {
@@ -635,8 +623,8 @@ static const struct dm_spi_ops ich_spi_ops = {
 };
 
 static const struct udevice_id ich_spi_ids[] = {
-	{ .compatible = "intel,ich7-spi" },
-	{ .compatible = "intel,ich9-spi" },
+	{ .compatible = "intel,ich7-spi", ICHV_7 },
+	{ .compatible = "intel,ich9-spi", ICHV_9 },
 	{ }
 };
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 079/108] spi: ich: Fix header order
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (55 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 078/108] spi: ich: Convert to livetree Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:53   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 080/108] spi: ich: Various small tidy-ups Simon Glass
                   ` (30 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Move the header files into the right order.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 7c29369a169..516b859a674 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <div64.h>
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
@@ -13,9 +14,8 @@
 #include <pci.h>
 #include <pci_ids.h>
 #include <spi.h>
-#include <asm/io.h>
 #include <spi-mem.h>
-#include <div64.h>
+#include <asm/io.h>
 
 #include "ich.h"
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 080/108] spi: ich: Various small tidy-ups
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (56 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 079/108] spi: ich: Fix header order Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 13:53   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata Simon Glass
                   ` (29 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Use debug() instead of printf() to reduce code size and change a bool
return value to the use the 'bool' type. Also drop the global data
declaration since it not actually used. Finally, set the log category.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 516b859a674..e2bc77bbd58 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -5,6 +5,8 @@
  * This file is derived from the flashrom project.
  */
 
+#define LOG_CATEGORY	UCLASS_SPI
+
 #include <common.h>
 #include <div64.h>
 #include <dm.h>
@@ -19,8 +21,6 @@
 
 #include "ich.h"
 
-DECLARE_GLOBAL_DATA_PTR;
-
 #ifdef DEBUG_TRACE
 #define debug_trace(fmt, args...) debug(fmt, ##args)
 #else
@@ -96,7 +96,7 @@ static void ich_set_bbar(struct ich_spi_priv *ctlr, uint32_t minaddr)
 }
 
 /* @return 1 if the SPI flash supports the 33MHz speed */
-static int ich9_can_do_33mhz(struct udevice *dev)
+static bool ich9_can_do_33mhz(struct udevice *dev)
 {
 	u32 fdod, speed;
 
@@ -172,8 +172,7 @@ static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans,
 		}
 
 		if (opcode_index == ctlr->menubytes) {
-			printf("ICH SPI: Opcode %x not found\n",
-			       trans->opcode);
+			debug("ICH SPI: Opcode %x not found\n", trans->opcode);
 			return -EINVAL;
 		}
 
@@ -181,8 +180,8 @@ static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans,
 		optype = (optypes >> (opcode_index * 2)) & 0x3;
 
 		if (optype != trans->type) {
-			printf("ICH SPI: Transaction doesn't fit type %d\n",
-			       optype);
+			debug("ICH SPI: Transaction doesn't fit type %d\n",
+			      optype);
 			return -ENOSPC;
 		}
 		return opcode_index;
@@ -213,9 +212,9 @@ static int ich_status_poll(struct ich_spi_priv *ctlr, u16 bitmask,
 		}
 		udelay(10);
 	}
+	debug("ICH SPI: SCIP timeout, read %x, expected %x, wts %x %x\n",
+	      status, bitmask, wait_til_set, status & bitmask);
 
-	printf("ICH SPI: SCIP timeout, read %x, expected %x\n",
-	       status, bitmask);
 	return -ETIMEDOUT;
 }
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (57 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 080/108] spi: ich: Various small tidy-ups Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:36   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size() Simon Glass
                   ` (28 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

It is useful to store the mmio base in platdata. It reduces the amount of
casting needed. Update the code and move the struct to the C file at the
same time, as we will need to use with of-platdata.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 27 +++++++++++++--------------
 drivers/spi/ich.h |  5 -----
 2 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index e2bc77bbd58..7f73f096ecb 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -27,6 +27,12 @@
 #define debug_trace(x, args...)
 #endif
 
+struct ich_spi_platdata {
+	enum ich_version ich_version;	/* Controller version, 7 or 9 */
+	bool lockdown;			/* lock down controller settings? */
+	ulong mmio_base;		/* Base of MMIO registers */
+};
+
 static u8 ich_readb(struct ich_spi_priv *priv, int reg)
 {
 	u8 value = readb(priv->base + reg);
@@ -466,16 +472,9 @@ static int ich_init_controller(struct udevice *dev,
 			       struct ich_spi_platdata *plat,
 			       struct ich_spi_priv *ctlr)
 {
-	ulong sbase_addr;
-	void *sbase;
-
-	/* SBASE is similar */
-	pch_get_spi_base(dev->parent, &sbase_addr);
-	sbase = (void *)sbase_addr;
-	debug("%s: sbase=%p\n", __func__, sbase);
-
+	ctlr->base = (void *)plat->mmio_base;
 	if (plat->ich_version == ICHV_7) {
-		struct ich7_spi_regs *ich7_spi = sbase;
+		struct ich7_spi_regs *ich7_spi = ctlr->base;
 
 		ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
 		ctlr->menubytes = sizeof(ich7_spi->opmenu);
@@ -487,9 +486,8 @@ static int ich_init_controller(struct udevice *dev,
 		ctlr->control = offsetof(struct ich7_spi_regs, spic);
 		ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
 		ctlr->preop = offsetof(struct ich7_spi_regs, preop);
-		ctlr->base = ich7_spi;
 	} else if (plat->ich_version == ICHV_9) {
-		struct ich9_spi_regs *ich9_spi = sbase;
+		struct ich9_spi_regs *ich9_spi = ctlr->base;
 
 		ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
 		ctlr->menubytes = sizeof(ich9_spi->opmenu);
@@ -504,7 +502,6 @@ static int ich_init_controller(struct udevice *dev,
 		ctlr->preop = offsetof(struct ich9_spi_regs, preop);
 		ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
 		ctlr->pr = &ich9_spi->pr[0];
-		ctlr->base = ich9_spi;
 	} else {
 		debug("ICH SPI: Unrecognised ICH version %d\n",
 		      plat->ich_version);
@@ -515,8 +512,8 @@ static int ich_init_controller(struct udevice *dev,
 	ctlr->max_speed = 20000000;
 	if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
 		ctlr->max_speed = 33000000;
-	debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
-	      plat->ich_version, ctlr->base, ctlr->max_speed);
+	debug("ICH SPI: Version ID %d detected at %lx, speed %ld\n",
+	      plat->ich_version, plat->mmio_base, ctlr->max_speed);
 
 	ich_set_bbar(ctlr, 0);
 
@@ -601,6 +598,8 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
 	plat->ich_version = dev_get_driver_data(dev);
 	plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
 
+	pch_get_spi_base(dev->parent, &plat->mmio_base);
+
 	return 0;
 }
 
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index 77057878a5d..623b2c547a6 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -168,11 +168,6 @@ enum ich_version {
 	ICHV_9,
 };
 
-struct ich_spi_platdata {
-	enum ich_version ich_version;	/* Controller version, 7 or 9 */
-	bool lockdown;			/* lock down controller settings? */
-};
-
 struct ich_spi_priv {
 	int opmenu;
 	int menubytes;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (58 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:36   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi Simon Glass
                   ` (27 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

This incorrectly shortens read operations if there is a maximum write size
but no maximum read size. Fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 7f73f096ecb..b28f3423584 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -424,9 +424,11 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
 		page_offset = do_div(aux, ICH_BOUNDARY);
 	}
 
-	if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
-		op->data.nbytes = min(ICH_BOUNDARY - page_offset,
-				      slave->max_read_size);
+	if (op->data.dir == SPI_MEM_DATA_IN) {
+		if (slave->max_read_size) {
+			op->data.nbytes = min(ICH_BOUNDARY - page_offset,
+					      slave->max_read_size);
+		}
 	} else if (slave->max_write_size) {
 		op->data.nbytes = min(ICH_BOUNDARY - page_offset,
 				      slave->max_write_size);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (59 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size() Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:36   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 084/108] spi: ich: Support hardware sequencing Simon Glass
                   ` (26 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

The Intel Fast SPI interface is similar to ICH. Add of-platdata support
for this using the "intel,fast-spi" compatible string.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index b28f3423584..ae3bff36bba 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <div64.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <errno.h>
 #include <malloc.h>
 #include <pch.h>
@@ -28,9 +29,13 @@
 #endif
 
 struct ich_spi_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_intel_fast_spi dtplat;
+#endif
 	enum ich_version ich_version;	/* Controller version, 7 or 9 */
 	bool lockdown;			/* lock down controller settings? */
 	ulong mmio_base;		/* Base of MMIO registers */
+	pci_dev_t bdf;			/* PCI address used by of-platdata */
 };
 
 static u8 ich_readb(struct ich_spi_priv *priv, int reg)
@@ -597,10 +602,16 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	plat->ich_version = dev_get_driver_data(dev);
 	plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
-
 	pch_get_spi_base(dev->parent, &plat->mmio_base);
+#else
+	plat->ich_version = ICHV_APL;
+	plat->mmio_base = plat->dtplat.early_regs[0];
+	plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
+#endif
+	debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
 
 	return 0;
 }
@@ -628,8 +639,8 @@ static const struct udevice_id ich_spi_ids[] = {
 	{ }
 };
 
-U_BOOT_DRIVER(ich_spi) = {
-	.name	= "ich_spi",
+U_BOOT_DRIVER(intel_fast_spi) = {
+	.name	= "intel_fast_spi",
 	.id	= UCLASS_SPI,
 	.of_match = ich_spi_ids,
 	.ops	= &ich_spi_ops,
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 084/108] spi: ich: Support hardware sequencing
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (60 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:36   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method Simon Glass
                   ` (25 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Apollolake (APL) only supports hardware sequencing. Add support for this
into the SPI driver, as an option.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 205 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/spi/ich.h |  39 +++++++++
 2 files changed, 241 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index ae3bff36bba..ae1dc64bde8 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -17,7 +17,9 @@
 #include <pci.h>
 #include <pci_ids.h>
 #include <spi.h>
+#include <spi_flash.h>
 #include <spi-mem.h>
+#include <asm/fast_spi.h>
 #include <asm/io.h>
 
 #include "ich.h"
@@ -36,6 +38,7 @@ struct ich_spi_platdata {
 	bool lockdown;			/* lock down controller settings? */
 	ulong mmio_base;		/* Base of MMIO registers */
 	pci_dev_t bdf;			/* PCI address used by of-platdata */
+	bool hwseq;			/* Use hardware sequencing (not s/w) */
 };
 
 static u8 ich_readb(struct ich_spi_priv *priv, int reg)
@@ -244,7 +247,8 @@ static void ich_spi_config_opcode(struct udevice *dev)
 	ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
 }
 
-static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
+static int ich_spi_exec_op_swseq(struct spi_slave *slave,
+				 const struct spi_mem_op *op)
 {
 	struct udevice *bus = dev_get_parent(slave->dev);
 	struct ich_spi_platdata *plat = dev_get_platdata(bus);
@@ -415,6 +419,197 @@ static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
 	return 0;
 }
 
+/*
+ * Ensure read/write xfer len is not greater than SPIBAR_FDATA_FIFO_SIZE and
+ * that the operation does not cross page boundary.
+ */
+static uint get_xfer_len(u32 offset, int len, int page_size)
+{
+	uint xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE);
+	uint bytes_left = ALIGN(offset, page_size) - offset;
+
+	if (bytes_left)
+		xfer_len = min(xfer_len, bytes_left);
+
+	return xfer_len;
+}
+
+/* Fill FDATAn FIFO in preparation for a write transaction */
+static void fill_xfer_fifo(struct fast_spi_regs *regs, const void *data,
+			   uint len)
+{
+	memcpy(regs->fdata, data, len);
+}
+
+/* Drain FDATAn FIFO after a read transaction populates data */
+static void drain_xfer_fifo(struct fast_spi_regs *regs, void *dest, uint len)
+{
+	memcpy(dest, regs->fdata, len);
+}
+
+/* Fire up a transfer using the hardware sequencer */
+static void start_hwseq_xfer(struct fast_spi_regs *regs, uint hsfsts_cycle,
+			     uint offset, uint len)
+{
+	/* Make sure all W1C status bits get cleared */
+	u32 hsfsts;
+
+	hsfsts = readl(&regs->hsfsts_ctl);
+	hsfsts &= ~(HSFSTS_FCYCLE_MASK | HSFSTS_FDBC_MASK);
+	hsfsts |= HSFSTS_AEL | HSFSTS_FCERR | HSFSTS_FDONE;
+
+	/* Set up transaction parameters */
+	hsfsts |= hsfsts_cycle << HSFSTS_FCYCLE_SHIFT;
+	hsfsts |= ((len - 1) << HSFSTS_FDBC_SHIFT) & HSFSTS_FDBC_MASK;
+	hsfsts |= HSFSTS_FGO;
+
+	writel(offset, &regs->faddr);
+	writel(hsfsts, &regs->hsfsts_ctl);
+}
+
+static int wait_for_hwseq_xfer(struct fast_spi_regs *regs, uint offset)
+{
+	ulong start;
+	u32 hsfsts;
+
+	start = get_timer(0);
+	do {
+		hsfsts = readl(&regs->hsfsts_ctl);
+		if (hsfsts & HSFSTS_FCERR) {
+			debug("SPI transaction error at offset %x HSFSTS = %08x\n",
+			      offset, hsfsts);
+			return -EIO;
+		}
+		if (hsfsts & HSFSTS_AEL)
+			return -EPERM;
+
+		if (hsfsts & HSFSTS_FDONE)
+			return 0;
+	} while (get_timer(start) < SPIBAR_HWSEQ_XFER_TIMEOUT_MS);
+
+	debug("SPI transaction timeout@offset %x HSFSTS = %08x, timer %d\n",
+	      offset, hsfsts, (uint)get_timer(start));
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * exec_sync_hwseq_xfer() - Execute FAST_SPI flash transfer
+ *
+ * This waits until complete or timeout
+ *
+ * @regs: SPI registers
+ * @hsfsts_cycle: Cycle type (enum hsfsts_cycle_t)
+ * @offset: Offset to access
+ * @len: Number of bytes to transfer (can be 0)
+ * @return 9 if OK, -EIO on flash-cycle error (FCERR), -EPERM on access error
+ *	(AEL), -ETIMEDOUT on timeout
+ */
+static int exec_sync_hwseq_xfer(struct fast_spi_regs *regs, uint hsfsts_cycle,
+				uint offset, uint len)
+{
+	start_hwseq_xfer(regs, hsfsts_cycle, offset, len);
+
+	return wait_for_hwseq_xfer(regs, offset);
+}
+
+static int ich_spi_exec_op_hwseq(struct spi_slave *slave,
+				 const struct spi_mem_op *op)
+{
+	struct spi_flash *flash = dev_get_uclass_priv(slave->dev);
+	struct udevice *bus = dev_get_parent(slave->dev);
+	struct ich_spi_priv *priv = dev_get_priv(bus);
+	struct fast_spi_regs *regs = priv->base;
+	uint page_size;
+	uint offset;
+	int cycle;
+	uint len;
+	bool out;
+	int ret;
+	u8 *buf;
+
+	offset = op->addr.val;
+	len = op->data.nbytes;
+
+	switch (op->cmd.opcode) {
+	case SPINOR_OP_RDID:
+		cycle = HSFSTS_CYCLE_RDID;
+		break;
+	case SPINOR_OP_READ_FAST:
+		cycle = HSFSTS_CYCLE_READ;
+		break;
+	case SPINOR_OP_PP:
+		cycle = HSFSTS_CYCLE_WRITE;
+		break;
+	case SPINOR_OP_WREN:
+		/* Nothing needs to be done */
+		return 0;
+	case SPINOR_OP_WRSR:
+		cycle = HSFSTS_CYCLE_WR_STATUS;
+		break;
+	case SPINOR_OP_RDSR:
+		cycle = HSFSTS_CYCLE_RD_STATUS;
+		break;
+	case SPINOR_OP_WRDI:
+		return 0;  /* ignore */
+	case SPINOR_OP_BE_4K:
+		cycle = HSFSTS_CYCLE_4K_ERASE;
+		while (len) {
+			uint xfer_len = 0x1000;
+
+			ret = exec_sync_hwseq_xfer(regs, cycle, offset, 0);
+			if (ret)
+				return ret;
+			offset += xfer_len;
+			len -= xfer_len;
+		}
+		return 0;
+	default:
+		debug("Unknown cycle %x\n", op->cmd.opcode);
+		return -EINVAL;
+	};
+
+	out = op->data.dir == SPI_MEM_DATA_OUT;
+	buf = out ? (u8 *)op->data.buf.out : op->data.buf.in;
+	page_size = flash->page_size ? : 256;
+
+	while (len) {
+		uint xfer_len = get_xfer_len(offset, len, page_size);
+
+		if (out)
+			fill_xfer_fifo(regs, buf, xfer_len);
+
+		ret = exec_sync_hwseq_xfer(regs, cycle, offset, xfer_len);
+		if (ret)
+			return ret;
+
+		if (!out)
+			drain_xfer_fifo(regs, buf, xfer_len);
+
+		offset += xfer_len;
+		buf += xfer_len;
+		len -= xfer_len;
+	}
+
+	return 0;
+}
+
+static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
+{
+	struct udevice *bus = dev_get_parent(slave->dev);
+	struct ich_spi_platdata *plat = dev_get_platdata(bus);
+	int ret;
+
+	bootstage_start(BOOTSTAGE_ID_ACCUM_SPI, "fast_spi");
+	if (plat->hwseq)
+		ret = ich_spi_exec_op_hwseq(slave, op);
+	else
+		ret = ich_spi_exec_op_swseq(slave, op);
+	bootstage_accum(BOOTSTAGE_ID_ACCUM_SPI);
+
+	return ret;
+}
+
 static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
 {
 	unsigned int page_offset;
@@ -585,9 +780,11 @@ static int ich_spi_child_pre_probe(struct udevice *dev)
 
 	/*
 	 * Yes this controller can only write a small number of bytes at
-	 * once! The limit is typically 64 bytes.
+	 * once! The limit is typically 64 bytes. For hardware sequencing a
+	 * a loop is used to get around this.
 	 */
-	slave->max_write_size = priv->databytes;
+	if (!plat->hwseq)
+		slave->max_write_size = priv->databytes;
 	/*
 	 * ICH 7 SPI controller only supports array read command
 	 * and byte program command for SST flash
@@ -606,10 +803,12 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
 	plat->ich_version = dev_get_driver_data(dev);
 	plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
 	pch_get_spi_base(dev->parent, &plat->mmio_base);
+	plat->hwseq = dev_read_u32_default(dev, "intel,hardware-seq", 0);
 #else
 	plat->ich_version = ICHV_APL;
 	plat->mmio_base = plat->dtplat.early_regs[0];
 	plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
+	plat->hwseq = plat->dtplat.intel_hardware_seq;
 #endif
 	debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
 
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index 623b2c547a6..c7cf37b9321 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -163,6 +163,45 @@ struct spi_trans {
 
 #define ICH_BOUNDARY	0x1000
 
+#define HSFSTS_FDBC_SHIFT	24
+#define HSFSTS_FDBC_MASK	(0x3f << HSFSTS_FDBC_SHIFT)
+#define HSFSTS_WET		BIT(21)
+#define HSFSTS_FCYCLE_SHIFT	17
+#define HSFSTS_FCYCLE_MASK	(0xf << HSFSTS_FCYCLE_SHIFT)
+
+/* Supported flash cycle types */
+enum hsfsts_cycle_t {
+	HSFSTS_CYCLE_READ	= 0,
+	HSFSTS_CYCLE_WRITE	= 2,
+	HSFSTS_CYCLE_4K_ERASE,
+	HSFSTS_CYCLE_64K_ERASE,
+	HSFSTS_CYCLE_RDSFDP,
+	HSFSTS_CYCLE_RDID,
+	HSFSTS_CYCLE_WR_STATUS,
+	HSFSTS_CYCLE_RD_STATUS,
+};
+
+#define HSFSTS_FGO		BIT(16)
+#define HSFSTS_FLOCKDN		BIT(15)
+#define HSFSTS_FDV		BIT(14)
+#define HSFSTS_FDOPSS		BIT(13)
+#define HSFSTS_WRSDIS		BIT(11)
+#define HSFSTS_SAF_CE		BIT(8)
+#define HSFSTS_SAF_ACTIVE	BIT(7)
+#define HSFSTS_SAF_LE		BIT(6)
+#define HSFSTS_SCIP		BIT(5)
+#define HSFSTS_SAF_DLE		BIT(4)
+#define HSFSTS_SAF_ERROR	BIT(3)
+#define HSFSTS_AEL		BIT(2)
+#define HSFSTS_FCERR		BIT(1)
+#define HSFSTS_FDONE		BIT(0)
+#define HSFSTS_W1C_BITS		0xff
+
+/* Maximum bytes of data that can fit in FDATAn (0x10) registers */
+#define SPIBAR_FDATA_FIFO_SIZE		0x40
+
+#define SPIBAR_HWSEQ_XFER_TIMEOUT_MS	5000
+
 enum ich_version {
 	ICHV_7,
 	ICHV_9,
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (61 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 084/108] spi: ich: Support hardware sequencing Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:36   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support Simon Glass
                   ` (24 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add this method so that the memory-mapped location of the SPI flash can
be queried.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index ae1dc64bde8..ec0f77f6e40 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -610,6 +610,37 @@ static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
 	return ret;
 }
 
+static int ich_get_mmap_bus(struct udevice *bus, ulong *map_basep,
+			    uint *map_sizep, uint *offsetp)
+{
+	pci_dev_t spi_bdf;
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct pci_child_platdata *pplat = dev_get_parent_platdata(bus);
+
+	spi_bdf = pplat->devfn;
+#else
+	struct ich_spi_platdata *plat = dev_get_platdata(bus);
+
+	/*
+	 * We cannot rely on plat->bdf being set up yet since this method can
+	 * be called before the device is probed. Use the of-platdata directly
+	 * instead.
+	 */
+	spi_bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
+#endif
+
+	return fast_spi_get_bios_mmap(spi_bdf, map_basep, map_sizep, offsetp);
+}
+
+static int ich_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
+			uint *offsetp)
+{
+	struct udevice *bus = dev_get_parent(dev);
+
+	return ich_get_mmap_bus(bus, map_basep, map_sizep, offsetp);
+}
+
 static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
 {
 	unsigned int page_offset;
@@ -826,6 +857,7 @@ static const struct dm_spi_ops ich_spi_ops = {
 	.set_speed	= ich_spi_set_speed,
 	.set_mode	= ich_spi_set_mode,
 	.mem_ops	= &ich_controller_mem_ops,
+	.get_mmap	= ich_get_mmap,
 	/*
 	 * cs_info is not needed, since we require all chip selects to be
 	 * in the device tree explicitly
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (62 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:52   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 087/108] spi: ich: Add Apollolake support Simon Glass
                   ` (23 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

In TPL we want to reduce code size and support running with CONFIG_PCI
disabled. Add special code to handle this using a fixed BAR programmed
into the SPI on boot. Also cache the SPI flash to speed up boot.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index ec0f77f6e40..daa69c25a3a 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -19,8 +19,10 @@
 #include <spi.h>
 #include <spi_flash.h>
 #include <spi-mem.h>
+#include <spl.h>
 #include <asm/fast_spi.h>
 #include <asm/io.h>
+#include <asm/mtrr.h>
 
 #include "ich.h"
 
@@ -114,6 +116,8 @@ static bool ich9_can_do_33mhz(struct udevice *dev)
 {
 	u32 fdod, speed;
 
+	if (!CONFIG_IS_ENABLED(PCI))
+		return false;
 	/* Observe SPI Descriptor Component Section 0 */
 	dm_pci_write_config32(dev->parent, 0xb0, 0x1000);
 
@@ -705,6 +709,15 @@ static int ich_init_controller(struct udevice *dev,
 			       struct ich_spi_platdata *plat,
 			       struct ich_spi_priv *ctlr)
 {
+	if (spl_phase() == PHASE_TPL) {
+		struct ich_spi_platdata *plat = dev_get_platdata(dev);
+		int ret;
+
+		ret = fast_spi_early_init(plat->bdf, plat->mmio_base);
+		if (ret)
+			return ret;
+	}
+
 	ctlr->base = (void *)plat->mmio_base;
 	if (plat->ich_version == ICHV_7) {
 		struct ich7_spi_regs *ich7_spi = ctlr->base;
@@ -753,6 +766,25 @@ static int ich_init_controller(struct udevice *dev,
 	return 0;
 }
 
+static int ich_cache_bios_region(struct udevice *dev)
+{
+	ulong map_base;
+	uint map_size;
+	uint offset;
+	ulong base;
+	int ret;
+
+	ret = ich_get_mmap_bus(dev, &map_base, &map_size, &offset);
+	if (ret)
+		return ret;
+
+	base = (4ULL << 30) - map_size;
+	mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
+	log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
+
+	return 0;
+}
+
 static int ich_spi_probe(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
@@ -766,10 +798,16 @@ static int ich_spi_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	ret = ich_protect_lockdown(dev);
-	if (ret)
-		return ret;
-
+	if (spl_phase() == PHASE_TPL) {
+		/* Cache the BIOS to speed things up */
+		ret = ich_cache_bios_region(dev);
+		if (ret)
+			return ret;
+	} else {
+		ret = ich_protect_lockdown(dev);
+		if (ret)
+			return ret;
+	}
 	priv->cur_speed = priv->max_speed;
 
 	return 0;
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 087/108] spi: ich: Add Apollolake support
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (63 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:52   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 088/108] mtd: spi: Export spi_flash_std_probe() Simon Glass
                   ` (22 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add support for Apollolake to the ICH driver. This involves adjusting the
mmio address and skipping setting of the bbar.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/spi/ich.c | 19 ++++++++++++++-----
 drivers/spi/ich.h |  1 +
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index daa69c25a3a..77ab951edc1 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -105,10 +105,12 @@ static void ich_set_bbar(struct ich_spi_priv *ctlr, uint32_t minaddr)
 	const uint32_t bbar_mask = 0x00ffff00;
 	uint32_t ichspi_bbar;
 
-	minaddr &= bbar_mask;
-	ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
-	ichspi_bbar |= minaddr;
-	ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
+	if (ctlr->bbar) {
+		minaddr &= bbar_mask;
+		ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
+		ichspi_bbar |= minaddr;
+		ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
+	}
 }
 
 /* @return 1 if the SPI flash supports the 33MHz speed */
@@ -748,6 +750,7 @@ static int ich_init_controller(struct udevice *dev,
 		ctlr->preop = offsetof(struct ich9_spi_regs, preop);
 		ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
 		ctlr->pr = &ich9_spi->pr[0];
+	} else if (plat->ich_version == ICHV_APL) {
 	} else {
 		debug("ICH SPI: Unrecognised ICH version %d\n",
 		      plat->ich_version);
@@ -871,7 +874,12 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	plat->ich_version = dev_get_driver_data(dev);
 	plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
-	pch_get_spi_base(dev->parent, &plat->mmio_base);
+	if (plat->ich_version == ICHV_APL) {
+		plat->mmio_base = dm_pci_read_bar32(dev, 0);
+	} else  {
+		/* SBASE is similar */
+		pch_get_spi_base(dev->parent, &plat->mmio_base);
+	}
 	plat->hwseq = dev_read_u32_default(dev, "intel,hardware-seq", 0);
 #else
 	plat->ich_version = ICHV_APL;
@@ -905,6 +913,7 @@ static const struct dm_spi_ops ich_spi_ops = {
 static const struct udevice_id ich_spi_ids[] = {
 	{ .compatible = "intel,ich7-spi", ICHV_7 },
 	{ .compatible = "intel,ich9-spi", ICHV_9 },
+	{ .compatible = "intel,fast-spi", ICHV_APL },
 	{ }
 };
 
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index c7cf37b9321..d7f1ffdf37d 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -205,6 +205,7 @@ enum hsfsts_cycle_t {
 enum ich_version {
 	ICHV_7,
 	ICHV_9,
+	ICHV_APL,
 };
 
 struct ich_spi_priv {
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 088/108] mtd: spi: Export spi_flash_std_probe()
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (64 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 087/108] spi: ich: Add Apollolake support Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:52   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 089/108] x86: apollolake: Add basic IO addresses Simon Glass
                   ` (21 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

With of-platdata we need to create drivers for particular chips, or at
least drivers that are separate from the standard code, since C structures
are created by dtoc which are private to that driver.

To avoid duplicating the probing code, export this probe function for use
by these drivers.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/mtd/spi/sf_probe.c |  2 +-
 include/spi_flash.h        | 12 ++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 73297e1a0a5..755aba27116 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -137,7 +137,7 @@ static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
 	return spi_flash_cmd_get_sw_write_prot(flash);
 }
 
-static int spi_flash_std_probe(struct udevice *dev)
+int spi_flash_std_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parent_priv(dev);
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 55b4721813a..0b23f57a71b 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -102,6 +102,18 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
  */
 int spl_flash_get_sw_write_prot(struct udevice *dev);
 
+/**
+ * spi_flash_std_probe() - Probe a SPI flash device
+ *
+ * This is the standard internal method for probing a SPI flash device to
+ * determine its type. It can be used in chip-specific drivers which need to
+ * do this, typically with of-platdata
+ *
+ * @dev: SPI-flash device to probe
+ * @return 0 if OK, -ve on error
+ */
+int spi_flash_std_probe(struct udevice *dev);
+
 int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
 			   unsigned int max_hz, unsigned int spi_mode,
 			   struct udevice **devp);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 089/108] x86: apollolake: Add basic IO addresses
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (65 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 088/108] mtd: spi: Export spi_flash_std_probe() Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-11-19 14:52   ` Bin Meng
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 090/108] x86: apollolake: Add PMC driver Simon Glass
                   ` (20 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add some fixed IO and mmap addresses for use in the device tree and with
some early-init code.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/include/asm/arch-apollolake/iomap.h | 28 ++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 arch/x86/include/asm/arch-apollolake/iomap.h

diff --git a/arch/x86/include/asm/arch-apollolake/iomap.h b/arch/x86/include/asm/arch-apollolake/iomap.h
new file mode 100644
index 00000000000..200c76a8eef
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/iomap.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Take from coreboot project file of the same name
+ */
+
+#ifndef __ARCH_IOMAP_H
+#define __ARCH_IOMAP_H
+
+#define TCO_BASE_ADDRESS	(ACPI_BASE_ADDRESS + 0x60)
+#define TCO_BASE_SIZE		0x20
+
+#define R_ACPI_PM1_TMR			0x8
+
+/* Put p2sb at 0xd0000000 in TPL */
+#define IOMAP_P2SB_BAR		0xd0000000
+
+#define IOMAP_SPI_BASE		0xfe010000
+/*
+ * Use UART2. To use UART1 you need to set '2' to '1', change device tree serial
+ * node name and 'reg' property, and update CONFIG_DEBUG_UART_BASE.
+ */
+#define PCH_DEV_UART		PCI_BDF(0, 0x18, 2)
+
+#define PCH_DEV_LPC		PCI_BDF(0, 0x1f, 0)
+#define PCH_DEV_SPI		PCI_BDF(0, 0x0d, 2)
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 090/108] x86: apollolake: Add PMC driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (66 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 089/108] x86: apollolake: Add basic IO addresses Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 091/108] x86: apollolake: Add low-power subsystem (lpss) support Simon Glass
                   ` (19 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add a driver for the apollolake SoC. It supports the basic operations and
can use device tree or of-platdata.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use pci_get_devfn()

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile          |   5 +
 arch/x86/cpu/apollolake/pmc.c             | 216 ++++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/pm.h |  19 ++
 drivers/power/acpi_pmc/acpi-pmc-uclass.c  |  51 +++++
 4 files changed, 291 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/Makefile
 create mode 100644 arch/x86/cpu/apollolake/pmc.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/pm.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
new file mode 100644
index 00000000000..5d98a5a6db2
--- /dev/null
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2016 Google, Inc
+
+obj-y += pmc.o
diff --git a/arch/x86/cpu/apollolake/pmc.c b/arch/x86/cpu/apollolake/pmc.c
new file mode 100644
index 00000000000..e075408fa6f
--- /dev/null
+++ b/arch/x86/cpu/apollolake/pmc.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot pmclib.c, pmc.c and pmutil.c
+ */
+
+#define LOG_CATEGORY UCLASS_ACPI_PMC
+
+#include <common.h>
+#include <acpi_s3.h>
+#include <dt-structs.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <power/acpi_pmc.h>
+
+#define GPIO_GPE_CFG		0x1050
+
+/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
+#define PRSTS			0x1000
+#define GEN_PMCON1		0x1020
+#define  COLD_BOOT_STS		BIT(27)
+#define  COLD_RESET_STS		BIT(26)
+#define  WARM_RESET_STS		BIT(25)
+#define  GLOBAL_RESET_STS	BIT(24)
+#define  SRS			BIT(20)
+#define  MS4V			BIT(18)
+#define  RPS			BIT(2)
+#define GEN_PMCON1_CLR1_BITS	(COLD_BOOT_STS | COLD_RESET_STS | \
+				 WARM_RESET_STS | GLOBAL_RESET_STS | \
+				 SRS | MS4V)
+#define GEN_PMCON2		0x1024
+#define GEN_PMCON3		0x1028
+
+/* Offset of TCO registers from ACPI base I/O address */
+#define TCO_REG_OFFSET		0x60
+#define TCO1_STS	0x64
+#define   DMISCI_STS	BIT(9)
+#define   BOOT_STS	BIT(18)
+#define TCO2_STS	0x66
+#define TCO1_CNT	0x68
+#define   TCO_LOCK	BIT(12)
+#define TCO2_CNT	0x6a
+
+enum {
+	ETR		= 0x1048,
+	CF9_LOCK        = 1UL << 31,
+	CF9_GLB_RST	= 1 << 20,
+};
+
+struct apl_pmc_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_intel_apl_pmc dtplat;
+#endif
+	pci_dev_t bdf;
+};
+
+static int apl_pmc_fill_power_state(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+	upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS);
+	upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS);
+
+	upriv->prsts = readl(upriv->pmc_bar0 + PRSTS);
+	upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1);
+	upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2);
+	upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3);
+
+	return 0;
+}
+
+static int apl_prev_sleep_state(struct udevice *dev, int prev_sleep_state)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+	/* WAK_STS bit will not be set when waking from G3 state */
+	if (!(upriv->pm1_sts & WAK_STS) &&
+	    (upriv->gen_pmcon1 & COLD_BOOT_STS))
+		prev_sleep_state = ACPI_S5;
+
+	return prev_sleep_state;
+}
+
+static int apl_disable_tco(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+	pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET);
+
+	return 0;
+}
+
+static int apl_global_reset_set_enable(struct udevice *dev, bool enable)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+	if (enable)
+		setbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
+	else
+		clrbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
+
+	return 0;
+}
+
+int apl_pmc_ofdata_to_uc_platdata(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	struct apl_pmc_platdata *plat = dev_get_platdata(dev);
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	u32 base[6];
+	int size;
+	int ret;
+
+	ret = dev_read_u32_array(dev, "early-regs", base, ARRAY_SIZE(base));
+	if (ret)
+		return log_msg_ret("Missing/short early-regs", ret);
+	upriv->pmc_bar0 = (void *)base[0];
+	upriv->pmc_bar2 = (void *)base[2];
+	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)
+		return log_msg_ret("Cannot read gpe0-dm", size);
+	upriv->gpe0_count = size / sizeof(u32);
+	ret = dev_read_u32_array(dev, "gpe0-dw", upriv->gpe0_dw,
+				 upriv->gpe0_count);
+	if (ret)
+		return log_msg_ret("Bad gpe0-dw", ret);
+
+	return pmc_ofdata_to_uc_platdata(dev);
+#else
+	struct dtd_intel_apl_pmc *dtplat = &plat->dtplat;
+
+	plat->bdf = pci_x86_ofplat_get_devfn(dtplat->reg[0]);
+	upriv->pmc_bar0 = (void *)dtplat->early_regs[0];
+	upriv->pmc_bar2 = (void *)dtplat->early_regs[2];
+	upriv->acpi_base = dtplat->early_regs[4];
+	upriv->gpe0_dwx_mask = dtplat->gpe0_dwx_mask;
+	upriv->gpe0_dwx_shift_base = dtplat->gpe0_dwx_shift_base;
+	upriv->gpe0_sts_reg = dtplat->gpe0_sts;
+	upriv->gpe0_sts_reg += upriv->acpi_base;
+	upriv->gpe0_en_reg = dtplat->gpe0_en;
+	upriv->gpe0_en_reg += upriv->acpi_base;
+	upriv->gpe0_count = min((int)ARRAY_SIZE(dtplat->gpe0_dw), GPE0_REG_MAX);
+	memcpy(upriv->gpe0_dw, dtplat->gpe0_dw, sizeof(dtplat->gpe0_dw));
+#endif
+	upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG);
+
+	return 0;
+}
+
+static int enable_pmcbar(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	struct apl_pmc_platdata *priv = dev_get_platdata(dev);
+	pci_dev_t pmc = priv->bdf;
+
+	/*
+	 * Set PMC base addresses and enable decoding. BARs 1 and 3 are 64-bit
+	 * BARs.
+	 */
+	pci_x86_write_config(pmc, PCI_BASE_ADDRESS_0, (ulong)upriv->pmc_bar0,
+			     PCI_SIZE_32);
+	pci_x86_write_config(pmc, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+	pci_x86_write_config(pmc, PCI_BASE_ADDRESS_2, (ulong)upriv->pmc_bar2,
+			     PCI_SIZE_32);
+	pci_x86_write_config(pmc, PCI_BASE_ADDRESS_3, 0, PCI_SIZE_32);
+	pci_x86_write_config(pmc, PCI_BASE_ADDRESS_4, upriv->acpi_base,
+			     PCI_SIZE_16);
+	pci_x86_write_config(pmc, PCI_COMMAND, PCI_COMMAND_IO |
+			     PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
+			     PCI_SIZE_16);
+
+	return 0;
+}
+
+static int apl_pmc_probe(struct udevice *dev)
+{
+	if (spl_phase() == PHASE_TPL)
+		return enable_pmcbar(dev);
+
+	return 0;
+}
+
+static struct acpi_pmc_ops apl_pmc_ops = {
+	.init			= apl_pmc_fill_power_state,
+	.prev_sleep_state	= apl_prev_sleep_state,
+	.disable_tco		= apl_disable_tco,
+	.global_reset_set_enable = apl_global_reset_set_enable,
+};
+
+static const struct udevice_id apl_pmc_ids[] = {
+	{ .compatible = "intel,apl-pmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(apl_pmc) = {
+	.name		= "intel_apl_pmc",
+	.id		= UCLASS_ACPI_PMC,
+	.of_match	= apl_pmc_ids,
+	.ofdata_to_platdata = apl_pmc_ofdata_to_uc_platdata,
+	.probe		= apl_pmc_probe,
+	.ops		= &apl_pmc_ops,
+	.platdata_auto_alloc_size = sizeof(struct apl_pmc_platdata),
+};
diff --git a/arch/x86/include/asm/arch-apollolake/pm.h b/arch/x86/include/asm/arch-apollolake/pm.h
new file mode 100644
index 00000000000..8226ee775e1
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/pm.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+
+#ifndef __ASM_ARCH_PM_H
+#define __ASM_ARCH_PM_H
+
+#define  PMC_GPE_SW_31_0	0
+#define  PMC_GPE_SW_63_32	1
+#define  PMC_GPE_NW_31_0	3
+#define  PMC_GPE_NW_63_32	4
+#define  PMC_GPE_NW_95_64	5
+#define  PMC_GPE_N_31_0		6
+#define  PMC_GPE_N_63_32	7
+#define  PMC_GPE_W_31_0		9
+
+#endif
diff --git a/drivers/power/acpi_pmc/acpi-pmc-uclass.c b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
index 8800afecf10..8ccd36427a5 100644
--- a/drivers/power/acpi_pmc/acpi-pmc-uclass.c
+++ b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
@@ -37,6 +37,57 @@ enum {
 	TCO1_CNT_HLT			= 1 << 11,
 };
 
+#ifdef CONFIG_X86
+static int gpe0_shift(struct acpi_pmc_upriv *upriv, int regnum)
+{
+	return upriv->gpe0_dwx_shift_base + regnum * 4;
+}
+
+int pmc_gpe_init(struct udevice *dev)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+	struct udevice *itss;
+	u32 *dw;
+	u32 gpio_cfg_mask;
+	u32 gpio_cfg;
+	int ret, i;
+	u32 mask;
+
+	dw = upriv->gpe0_dw;
+	mask = upriv->gpe0_dwx_mask;
+	gpio_cfg_mask = 0;
+	for (i = 0; i < upriv->gpe0_count; i++) {
+		gpio_cfg_mask |= mask << gpe0_shift(upriv, i);
+		if (dw[i] & mask)
+			return log_msg_ret("Base GPE0 value", -EINVAL);
+	}
+
+	/*
+	 * Route the GPIOs to the GPE0 block. Determine that all values
+	 * are different and if they aren't, use the reset values.
+	 */
+	if (dw[0] == dw[1] || dw[1] == dw[2]) {
+		log_info("PMC: Using default GPE route");
+		gpio_cfg = readl(upriv->gpe_cfg);
+		for (i = 0; i < upriv->gpe0_count; i++)
+			dw[i] = gpio_cfg >> gpe0_shift(upriv, i);
+	} else {
+		gpio_cfg = 0;
+		for (i = 0; i < upriv->gpe0_count; i++)
+			gpio_cfg |= dw[i] << gpe0_shift(upriv, i);
+		clrsetbits_le32(upriv->gpe_cfg, gpio_cfg_mask, gpio_cfg);
+	}
+
+	/* Set the routes in the GPIO communities as well */
+	ret = uclass_first_device_err(UCLASS_IRQ, &itss);
+	if (ret)
+		return log_msg_ret("Cannot find itss", ret);
+	gpio_route_gpe(itss, dw[0], dw[1], dw[2]);
+
+	return 0;
+}
+#endif /* CONFIG_X86 */
+
 static void pmc_fill_pm_reg_info(struct udevice *dev)
 {
 	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 091/108] x86: apollolake: Add low-power subsystem (lpss) support
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (67 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 090/108] x86: apollolake: Add PMC driver Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  8:14   ` Andy Shevchenko
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver Simon Glass
                   ` (18 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add very basic support for taking an lpss device out of reset.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/apollolake/Makefile |  1 +
 arch/x86/cpu/apollolake/lpss.c   | 31 +++++++++++++++++++++++++++++++
 arch/x86/include/asm/lpss.h      | 11 +++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/lpss.c
 create mode 100644 arch/x86/include/asm/lpss.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 5d98a5a6db2..b58ef8e019c 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -2,4 +2,5 @@
 #
 # Copyright (c) 2016 Google, Inc
 
+obj-y += lpss.o
 obj-y += pmc.o
diff --git a/arch/x86/cpu/apollolake/lpss.c b/arch/x86/cpu/apollolake/lpss.c
new file mode 100644
index 00000000000..2f4aea79c07
--- /dev/null
+++ b/arch/x86/cpu/apollolake/lpss.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Special driver to handle of-platdata
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Some code from coreboot lpss.c
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/lpss.h>
+
+enum {
+	LPSS_RESET_CTL_REG	= 0x204,
+
+	/*
+	 * Bit 1:0 controls LPSS controller reset.
+	 *
+	 * 00 ->LPSS Host Controller is in reset (Reset Asserted)
+	 * 01/10 ->Reserved
+	 * 11 ->LPSS Host Controller is NOT at reset (Reset Released)
+	 */
+	LPSS_CNT_RST_RELEASE	= 3,
+};
+
+/* Take controller out of reset */
+void lpss_reset_release(void *regs)
+{
+	writel(LPSS_CNT_RST_RELEASE, regs + LPSS_RESET_CTL_REG);
+}
diff --git a/arch/x86/include/asm/lpss.h b/arch/x86/include/asm/lpss.h
new file mode 100644
index 00000000000..4bd56a5fa30
--- /dev/null
+++ b/arch/x86/include/asm/lpss.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ASM_LPSS_H
+#define __ASM_LPSS_H
+
+void lpss_reset_release(void *regs);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (68 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 091/108] x86: apollolake: Add low-power subsystem (lpss) support Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  7:46   ` Andy Shevchenko
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 093/108] x86: apollolake: Add GPIO driver Simon Glass
                   ` (17 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add a driver for the apollolake UART. It uses the standard ns16550 device
but also sets up the input clock with LPSS and supports configuration via
of-platdata.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use the LPSS code from a separate file

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile            |   1 +
 arch/x86/cpu/apollolake/uart.c              | 141 ++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/uart.h |  17 +++
 3 files changed, 159 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/uart.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/uart.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index b58ef8e019c..ff42d0fd619 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -4,3 +4,4 @@
 
 obj-y += lpss.o
 obj-y += pmc.o
+obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/uart.c b/arch/x86/cpu/apollolake/uart.c
new file mode 100644
index 00000000000..66744937dcb
--- /dev/null
+++ b/arch/x86/cpu/apollolake/uart.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Special driver to handle of-platdata
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Some code from coreboot lpss.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <ns16550.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/lpss.h>
+
+/* Low-power Subsystem (LPSS) clock register */
+enum {
+	LPSS_CLOCK_CTL_REG	= 0x200,
+	LPSS_CNT_CLOCK_EN	= 1,
+	LPSS_CNT_CLK_UPDATE	= 1U << 31,
+	LPSS_CLOCK_DIV_N_SHIFT	= 16,
+	LPSS_CLOCK_DIV_N_MASK	= 0x7fff << LPSS_CLOCK_DIV_N_SHIFT,
+	LPSS_CLOCK_DIV_M_SHIFT	= 1,
+	LPSS_CLOCK_DIV_M_MASK	= 0x7fff << LPSS_CLOCK_DIV_M_SHIFT,
+
+	/* These set the UART input clock speed */
+	LPSS_UART_CLK_M_VAL	= 0x25a,
+	LPSS_UART_CLK_N_VAL	= 0x7fff,
+};
+
+static void lpss_clk_update(void *regs, u32 clk_m_val, u32 clk_n_val)
+{
+	u32 clk_sel;
+
+	clk_sel = clk_n_val << LPSS_CLOCK_DIV_N_SHIFT |
+		 clk_m_val << LPSS_CLOCK_DIV_M_SHIFT;
+	clk_sel |= LPSS_CNT_CLK_UPDATE | LPSS_CNT_CLOCK_EN;
+
+	writel(clk_sel, regs + LPSS_CLOCK_CTL_REG);
+}
+
+static void uart_lpss_init(void *regs)
+{
+	/* Take UART out of reset */
+	lpss_reset_release(regs);
+
+	/* Set M and N divisor inputs and enable clock */
+	lpss_clk_update(regs, LPSS_UART_CLK_M_VAL, LPSS_UART_CLK_N_VAL);
+}
+
+void apl_uart_init(pci_dev_t bdf, ulong base)
+{
+	/* Set UART base address */
+	pci_x86_write_config(bdf, PCI_BASE_ADDRESS_0, base, PCI_SIZE_32);
+
+	/* Enable memory access and bus master */
+	pci_x86_write_config(bdf, PCI_COMMAND, PCI_COMMAND_MEMORY |
+			     PCI_COMMAND_MASTER, PCI_SIZE_32);
+
+	uart_lpss_init((void *)base);
+}
+
+/*
+ * This driver uses its own compatible string but almost everything else from
+ * the standard ns16550 driver. This allows us to provide an of-platdata
+ * implementation, since the platdata produced by of-platdata does not match
+ * struct ns16550_platdata.
+ *
+ * When running with of-platdata (generally TPL), the platdata is converted to
+ * something that ns16550 expects. When running withoutof-platdata (SPL, U-Boot
+ * proper), we use ns16550's ofdata_to_platdata routine.
+ */
+
+static int apl_ns16550_probe(struct udevice *dev)
+{
+	struct ns16550_platdata *plat = dev_get_platdata(dev);
+
+	if (!CONFIG_IS_ENABLED(PCI))
+		apl_uart_init(plat->bdf, plat->base);
+
+	return ns16550_serial_probe(dev);
+}
+
+static int apl_ns16550_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ns16550_platdata *plat;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_intel_apl_ns16550 *dtplat = dev_get_platdata(dev);
+
+	/*
+	 * Convert our platdata to the ns16550's platdata, so we can just use
+	 * that driver
+	 */
+	plat = malloc(sizeof(*plat));
+	if (!plat)
+		return -ENOMEM;
+	plat->base = dtplat->early_regs[0];
+	plat->reg_width = 1;
+	plat->reg_shift = dtplat->reg_shift;
+	plat->reg_offset = 0;
+	plat->clock = dtplat->clock_frequency;
+	plat->fcr = UART_FCR_DEFVAL;
+	plat->bdf = pci_x86_ofplat_get_devfn(dtplat->reg[0]);
+	dev->platdata = plat;
+#else
+	int ret;
+
+	ret = ns16550_serial_ofdata_to_platdata(dev);
+	if (ret)
+		return ret;
+	if (!CONFIG_IS_ENABLED(OF_TRANSLATE)) {
+		/*
+		 * Without address translation we cannot get correct PCI
+		 * address, so just read the BAR manually.
+		 */
+		plat = dev_get_platdata(dev);
+		plat->base = dm_pci_read_bar32(dev, 0);
+	}
+#endif /* OF_PLATDATA */
+
+	return 0;
+}
+
+static const struct udevice_id apl_ns16550_serial_ids[] = {
+	{ .compatible = "intel,apl-ns16550" },
+	{ },
+};
+
+U_BOOT_DRIVER(apl_ns16550) = {
+	.name	= "intel_apl_ns16550",
+	.id	= UCLASS_SERIAL,
+	.of_match = apl_ns16550_serial_ids,
+	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.ops	= &ns16550_serial_ops,
+	.ofdata_to_platdata = apl_ns16550_ofdata_to_platdata,
+	.probe = apl_ns16550_probe,
+};
diff --git a/arch/x86/include/asm/arch-apollolake/uart.h b/arch/x86/include/asm/arch-apollolake/uart.h
new file mode 100644
index 00000000000..521316d0a93
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/uart.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ASM_ARCH_UART_H
+#define __ASM_ARCH_UART_H
+
+/**
+ * apl_uart_init() - Set up the APL UART device and clock
+ *
+ * The UART won't actually work unless the GPIO settings are correct and the
+ * signals actually exit the SoC. See init_for_uart() for that.
+ */
+int apl_uart_init(pci_dev_t bdf, ulong base);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 093/108] x86: apollolake: Add GPIO driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (69 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-21  7:57   ` Andy Shevchenko
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 094/108] i2c: designware: Add apollolake support Simon Glass
                   ` (16 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

Add a driver for the apollolake GPIOs. It also handles pinctrl since this
is not very well separated on x86.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Fix mixed case in GPIO defines
- Rework how pads configuration is defined in TPL and SPL
- Use the IRQ uclass instead of ITSS

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile              |   1 +
 arch/x86/cpu/apollolake/gpio.c                | 735 ++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/gpio.h   | 180 +++++
 .../include/asm/arch-apollolake/gpio_apl.h    | 491 ++++++++++++
 .../include/asm/arch-apollolake/gpio_defs.h   | 398 ++++++++++
 5 files changed, 1805 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/gpio.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/gpio.h
 create mode 100644 arch/x86/include/asm/arch-apollolake/gpio_apl.h
 create mode 100644 arch/x86/include/asm/arch-apollolake/gpio_defs.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index ff42d0fd619..fa53ea10b79 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -2,6 +2,7 @@
 #
 # Copyright (c) 2016 Google, Inc
 
+obj-y += gpio.o
 obj-y += lpss.o
 obj-y += pmc.o
 obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/gpio.c b/arch/x86/cpu/apollolake/gpio.c
new file mode 100644
index 00000000000..80364006ef0
--- /dev/null
+++ b/arch/x86/cpu/apollolake/gpio.c
@@ -0,0 +1,735 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Intel Corp.
+ * Copyright 2019 Google LLC
+ *
+ * Taken partly from coreboot gpio.c
+ */
+
+#define LOG_CATEGORY UCLASS_GPIO
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <irq.h>
+#include <p2sb.h>
+#include <spl.h>
+#include <asm-generic/gpio.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/gpio_defs.h>
+#include <asm/arch/itss.h>
+
+/**
+ * struct apl_gpio_platdata - platform data for each device
+ *
+ * @dtplat: of-platdata data from C struct
+ * @num_cfgs: Number of configuration words for each pad
+ * @comm: Pad community for this device
+ */
+struct apl_gpio_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	/* Put this first since driver model will copy the data here */
+	struct dtd_intel_apl_gpio dtplat;
+#endif
+	int num_cfgs;
+	const struct pad_community *comm;
+};
+
+/** struct apl_gpio_priv - private data for each device
+ *
+ * @itss: ITSS device (for interrupt handling)
+ * @itss_pol_cfg: Use to program Interrupt Polarity Control (IPCx) register
+ *	Each bit represents IRQx Active High Polarity Disable configuration:
+ *	when set to 1, the interrupt polarity associated with IRQx is inverted
+ *	to appear as Active Low to IOAPIC and vice versa
+ */
+struct apl_gpio_priv {
+	struct udevice *itss;
+	bool itss_pol_cfg;
+};
+
+#define GPIO_DWx_SIZE(x)	(sizeof(u32) * (x))
+#define PAD_CFG_OFFSET(x, dw_num)	((x) + GPIO_DWx_SIZE(dw_num))
+#define PAD_CFG0_OFFSET(x)	PAD_CFG_OFFSET(x, 0)
+#define PAD_CFG1_OFFSET(x)	PAD_CFG_OFFSET(x, 1)
+
+#define MISCCFG_GPE0_DW0_SHIFT 8
+#define MISCCFG_GPE0_DW0_MASK (0xf << MISCCFG_GPE0_DW0_SHIFT)
+#define MISCCFG_GPE0_DW1_SHIFT 12
+#define MISCCFG_GPE0_DW1_MASK (0xf << MISCCFG_GPE0_DW1_SHIFT)
+#define MISCCFG_GPE0_DW2_SHIFT 16
+#define MISCCFG_GPE0_DW2_MASK (0xf << MISCCFG_GPE0_DW2_SHIFT)
+
+#define GPI_SMI_STS_OFFSET(comm, group) ((comm)->gpi_smi_sts_reg_0 +	\
+				((group) * sizeof(u32)))
+#define GPI_SMI_EN_OFFSET(comm, group) ((comm)->gpi_smi_en_reg_0 +	\
+				((group) * sizeof(u32)))
+#define GPI_IS_OFFSET(comm, group) ((comm)->gpi_int_sts_reg_0 +	\
+				((group) * sizeof(uint32_t)))
+#define GPI_IE_OFFSET(comm, group) ((comm)->gpi_int_en_reg_0 +	\
+				((group) * sizeof(uint32_t)))
+
+static const struct reset_mapping rst_map[] = {
+	{ .logical = PAD_CFG0_LOGICAL_RESET_PWROK, .chipset = 0U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 },
+};
+
+static const struct pad_group apl_community_n_groups[] = {
+	INTEL_GPP(N_OFFSET, N_OFFSET, GPIO_31),	/* NORTH 0 */
+	INTEL_GPP(N_OFFSET, GPIO_32, JTAG_TRST_B),	/* NORTH 1 */
+	INTEL_GPP(N_OFFSET, JTAG_TMS, SVID0_CLK),	/* NORTH 2 */
+};
+
+static const struct pad_group apl_community_w_groups[] = {
+	INTEL_GPP(W_OFFSET, W_OFFSET, OSC_CLK_OUT_1),/* WEST 0 */
+	INTEL_GPP(W_OFFSET, OSC_CLK_OUT_2, SUSPWRDNACK),/* WEST 1 */
+};
+
+static const struct pad_group apl_community_sw_groups[] = {
+	INTEL_GPP(SW_OFFSET, SW_OFFSET, SMB_ALERTB),	/* SOUTHWEST 0 */
+	INTEL_GPP(SW_OFFSET, SMB_CLK, LPC_FRAMEB),	/* SOUTHWEST 1 */
+};
+
+static const struct pad_group apl_community_nw_groups[] = {
+	INTEL_GPP(NW_OFFSET, NW_OFFSET, PROCHOT_B),	/* NORTHWEST 0 */
+	INTEL_GPP(NW_OFFSET, PMIC_I2C_SCL, GPIO_106),/* NORTHWEST 1 */
+	INTEL_GPP(NW_OFFSET, GPIO_109, GPIO_123),	/* NORTHWEST 2 */
+};
+
+/* TODO(sjg@chromium.org): Consider moving this to device tree */
+static const struct pad_community apl_gpio_communities[] = {
+	{
+		.port = PID_GPIO_N,
+		.first_pad = N_OFFSET,
+		.last_pad = SVID0_CLK,
+		.num_gpi_regs = NUM_N_GPI_REGS,
+		.gpi_status_offset = NUM_NW_GPI_REGS + NUM_W_GPI_REGS
+			+ NUM_SW_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPIO_GPE_N",
+		.acpi_path = "\\_SB.GPO0",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = apl_community_n_groups,
+		.num_groups = ARRAY_SIZE(apl_community_n_groups),
+	}, {
+		.port = PID_GPIO_NW,
+		.first_pad = NW_OFFSET,
+		.last_pad = GPIO_123,
+		.num_gpi_regs = NUM_NW_GPI_REGS,
+		.gpi_status_offset = NUM_W_GPI_REGS + NUM_SW_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPIO_GPE_NW",
+		.acpi_path = "\\_SB.GPO1",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = apl_community_nw_groups,
+		.num_groups = ARRAY_SIZE(apl_community_nw_groups),
+	}, {
+		.port = PID_GPIO_W,
+		.first_pad = W_OFFSET,
+		.last_pad = SUSPWRDNACK,
+		.num_gpi_regs = NUM_W_GPI_REGS,
+		.gpi_status_offset = NUM_SW_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPIO_GPE_W",
+		.acpi_path = "\\_SB.GPO2",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = apl_community_w_groups,
+		.num_groups = ARRAY_SIZE(apl_community_w_groups),
+	}, {
+		.port = PID_GPIO_SW,
+		.first_pad = SW_OFFSET,
+		.last_pad = LPC_FRAMEB,
+		.num_gpi_regs = NUM_SW_GPI_REGS,
+		.gpi_status_offset = 0,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPIO_GPE_SW",
+		.acpi_path = "\\_SB.GPO3",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = apl_community_sw_groups,
+		.num_groups = ARRAY_SIZE(apl_community_sw_groups),
+	},
+};
+
+static size_t relative_pad_in_comm(const struct pad_community *comm,
+				   uint gpio)
+{
+	return gpio - comm->first_pad;
+}
+
+/* find the group within the community that the pad is a part of */
+static int gpio_group_index(const struct pad_community *comm, uint relative_pad)
+{
+	int i;
+
+	if (!comm->groups)
+		return -ESPIPE;
+
+	/* find the base pad number for this pad's group */
+	for (i = 0; i < comm->num_groups; i++) {
+		if (relative_pad >= comm->groups[i].first_pad &&
+		    relative_pad < comm->groups[i].first_pad +
+		    comm->groups[i].size)
+			return i;
+	}
+
+	return -ENOENT;
+}
+
+static int gpio_group_index_scaled(const struct pad_community *comm,
+				   uint relative_pad, size_t scale)
+{
+	int ret;
+
+	ret = gpio_group_index(comm, relative_pad);
+	if (ret < 0)
+		return ret;
+
+	return ret * scale;
+}
+
+static int gpio_within_group(const struct pad_community *comm,
+			     uint relative_pad)
+{
+	int ret;
+
+	ret = gpio_group_index(comm, relative_pad);
+	if (ret < 0)
+		return ret;
+
+	return relative_pad - comm->groups[ret].first_pad;
+}
+
+static u32 gpio_bitmask_within_group(const struct pad_community *comm,
+				     uint relative_pad)
+{
+	return 1U << gpio_within_group(comm, relative_pad);
+}
+
+/**
+ * gpio_get_device() - Find the device for a particular pad
+ *
+ * Each GPIO device is attached to one community and this supports a number of
+ * GPIO pins. This function finds the device which controls a particular pad.
+ *
+ * @pad: Pad to check
+ * @devp: Returns the device for that pad
+ * @return 0 if OK, -ENOTBLK if no device was found for the given pin
+ */
+static int gpio_get_device(uint pad, struct udevice **devp)
+{
+	struct udevice *dev;
+
+	/*
+	 * We have to probe each one of these since the community link is only
+	 * attached in apl_gpio_ofdata_to_platdata().
+	 */
+	uclass_foreach_dev_probe(UCLASS_GPIO, dev) {
+		struct apl_gpio_platdata *plat = dev_get_platdata(dev);
+		const struct pad_community *comm = plat->comm;
+
+		if (pad >= comm->first_pad && pad <= comm->last_pad) {
+			*devp = dev;
+			return 0;
+		}
+	}
+	printf("pad %d not found\n", pad);
+
+	return -ENOTBLK;
+}
+
+static int gpio_configure_owner(struct udevice *dev,
+				const struct pad_config *cfg,
+				const struct pad_community *comm)
+{
+	u32 hostsw_own;
+	u16 hostsw_own_offset;
+	int pin;
+	int ret;
+
+	pin = relative_pad_in_comm(comm, cfg->pad);
+
+	/* Based on the gpio pin number configure the corresponding bit in
+	 * HOSTSW_OWN register. Value of 0x1 indicates GPIO Driver onwership.
+	 */
+	hostsw_own_offset = comm->host_own_reg_0;
+	ret = gpio_group_index_scaled(comm, pin, sizeof(u32));
+	if (ret < 0)
+		return ret;
+	hostsw_own_offset += ret;
+
+	hostsw_own = pcr_read32(dev, hostsw_own_offset);
+
+	/* The 4th bit in pad_config 1 (RO) is used to indicate if the pad
+	 * needs GPIO driver ownership.  Set the bit if GPIO driver ownership
+	 * requested, otherwise clear the bit.
+	 */
+	if (cfg->pad_config[1] & PAD_CFG1_GPIO_DRIVER)
+		hostsw_own |= gpio_bitmask_within_group(comm, pin);
+	else
+		hostsw_own &= ~gpio_bitmask_within_group(comm, pin);
+
+	pcr_write32(dev, hostsw_own_offset, hostsw_own);
+
+	return 0;
+}
+
+static int gpi_enable_smi(struct udevice *dev, const struct pad_config *cfg,
+			  const struct pad_community *comm)
+{
+	u32 value;
+	u16 sts_reg;
+	u16 en_reg;
+	int group;
+	int pin;
+	int ret;
+
+	if ((cfg->pad_config[0] & PAD_CFG0_ROUTE_SMI) != PAD_CFG0_ROUTE_SMI)
+		return 0;
+
+	pin = relative_pad_in_comm(comm, cfg->pad);
+	ret = gpio_group_index(comm, pin);
+	if (ret < 0)
+		return ret;
+	group = ret;
+
+	sts_reg = GPI_SMI_STS_OFFSET(comm, group);
+	value = pcr_read32(dev, sts_reg);
+	/* Write back 1 to reset the sts bits */
+	pcr_write32(dev, sts_reg, value);
+
+	/* Set enable bits */
+	en_reg = GPI_SMI_EN_OFFSET(comm, group);
+	pcr_setbits32(dev, en_reg, gpio_bitmask_within_group(comm, pin));
+
+	return 0;
+}
+
+static int gpio_configure_itss(struct udevice *dev,
+			       const struct pad_config *cfg,
+			       uint pad_cfg_offset)
+{
+	struct apl_gpio_priv *priv = dev_get_priv(dev);
+
+	if (!priv->itss_pol_cfg)
+		return -ENOSYS;
+
+	int irq;
+
+	/* Set up ITSS polarity if pad is routed to APIC.
+	 *
+	 * The ITSS takes only active high interrupt signals. Therefore,
+	 * if the pad configuration indicates an inversion assume the
+	 * intent is for the ITSS polarity. Before forwarding on the
+	 * request to the APIC there's an inversion setting for how the
+	 * signal is forwarded to the APIC. Honor the inversion setting
+	 * in the GPIO pad configuration so that a hardware active low
+	 * signal looks that way to the APIC (double inversion).
+	 */
+	if (!(cfg->pad_config[0] & PAD_CFG0_ROUTE_IOAPIC))
+		return 0;
+
+	irq = pcr_read32(dev, PAD_CFG1_OFFSET(pad_cfg_offset));
+	irq &= PAD_CFG1_IRQ_MASK;
+	if (!irq) {
+		log_err("GPIO %u doesn't support APIC routing\n", cfg->pad);
+
+		return -EPROTONOSUPPORT;
+	}
+	irq_set_polarity(priv->itss, irq,
+			 cfg->pad_config[0] & PAD_CFG0_RX_POL_INVERT);
+
+	return 0;
+}
+
+/* Number of DWx config registers can be different for different SOCs */
+static uint pad_config_offset(const struct pad_community *comm, uint pad)
+{
+	size_t offset;
+
+	offset = relative_pad_in_comm(comm, pad);
+	offset *= GPIO_DWx_SIZE(GPIO_NUM_PAD_CFG_REGS);
+
+	return offset + comm->pad_cfg_base;
+}
+
+static int gpio_pad_reset_config_override(const struct pad_community *comm,
+					  u32 config_value)
+{
+	const struct reset_mapping *rst_map = comm->reset_map;
+	int i;
+
+	/* Logical reset values equal chipset values */
+	if (!rst_map || !comm->num_reset_vals)
+		return config_value;
+
+	for (i = 0; i < comm->num_reset_vals; i++, rst_map++) {
+		if ((config_value & PAD_CFG0_RESET_MASK) == rst_map->logical) {
+			config_value &= ~PAD_CFG0_RESET_MASK;
+			config_value |= rst_map->chipset;
+
+			return config_value;
+		}
+	}
+	log_err("Logical-to-Chipset mapping not found\n");
+
+	return -ENOENT;
+}
+
+static const int mask[4] = {
+	PAD_CFG0_TX_STATE |
+	PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE | PAD_CFG0_MODE_MASK |
+	PAD_CFG0_ROUTE_MASK | PAD_CFG0_RXTENCFG_MASK |
+	PAD_CFG0_RXINV_MASK | PAD_CFG0_PREGFRXSEL |
+	PAD_CFG0_TRIG_MASK | PAD_CFG0_RXRAW1_MASK |
+	PAD_CFG0_RXPADSTSEL_MASK | PAD_CFG0_RESET_MASK,
+
+#ifdef CONFIG_INTEL_GPIO_IOSTANDBY
+	PAD_CFG1_IOSTERM_MASK | PAD_CFG1_PULL_MASK | PAD_CFG1_IOSSTATE_MASK,
+#else
+	PAD_CFG1_IOSTERM_MASK | PAD_CFG1_PULL_MASK,
+#endif
+
+	PAD_CFG2_DEBOUNCE_MASK,
+
+	0,
+};
+
+/**
+ * gpio_configure_pad() - Configure a pad
+ *
+ * @dev: GPIO device containing the pad (see gpio_get_device())
+ * @cfg: Configuration to apply
+ * @return 0 if OK, -ve on error
+ */
+static int gpio_configure_pad(struct udevice *dev, const struct pad_config *cfg)
+{
+	struct apl_gpio_platdata *plat = dev_get_platdata(dev);
+	const struct pad_community *comm = plat->comm;
+	uint config_offset;
+	u32 pad_conf, soc_pad_conf;
+	int ret;
+	int i;
+
+	if (IS_ERR(comm))
+		return PTR_ERR(comm);
+	config_offset = pad_config_offset(comm, cfg->pad);
+	for (i = 0; i < GPIO_NUM_PAD_CFG_REGS; i++) {
+		pad_conf = pcr_read32(dev, PAD_CFG_OFFSET(config_offset, i));
+
+		soc_pad_conf = cfg->pad_config[i];
+		if (i == 0) {
+			ret = gpio_pad_reset_config_override(comm,
+							     soc_pad_conf);
+			if (ret < 0)
+				return ret;
+			soc_pad_conf = ret;
+		}
+		soc_pad_conf &= mask[i];
+		soc_pad_conf |= pad_conf & ~mask[i];
+
+		log_debug("gpio_padcfg [0x%02x, %02zd] DW%d [0x%08x : 0x%08x : 0x%08x]\n",
+			  comm->port, relative_pad_in_comm(comm, cfg->pad), i,
+			  pad_conf,/* old value */
+			  cfg->pad_config[i], /* value passed from gpio table */
+			  soc_pad_conf); /*new value*/
+		pcr_write32(dev, PAD_CFG_OFFSET(config_offset, i),
+			    soc_pad_conf);
+	}
+	ret = gpio_configure_itss(dev, cfg, config_offset);
+	if (ret && ret != -ENOSYS)
+		return log_msg_ret("itss config failed", ret);
+	ret = gpio_configure_owner(dev, cfg, comm);
+	if (ret)
+		return ret;
+	ret = gpi_enable_smi(dev, cfg, comm);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static u32 get_config_reg_addr(struct udevice *dev, uint offset)
+{
+	struct apl_gpio_platdata *plat = dev_get_platdata(dev);
+	const struct pad_community *comm = plat->comm;
+	uint config_offset;
+
+	config_offset = comm->pad_cfg_base + offset *
+		 GPIO_DWx_SIZE(GPIO_NUM_PAD_CFG_REGS);
+
+	return config_offset;
+}
+
+static u32 get_config_reg(struct udevice *dev, uint offset)
+{
+	uint config_offset = get_config_reg_addr(dev, offset);
+
+	return pcr_read32(dev, config_offset);
+}
+
+static int apl_gpio_direction_input(struct udevice *dev, uint offset)
+{
+	uint config_offset = get_config_reg_addr(dev, offset);
+
+	pcr_clrsetbits32(dev, config_offset,
+			 PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
+				  PAD_CFG0_RX_DISABLE,
+			 PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE);
+
+	return 0;
+}
+
+static int apl_gpio_direction_output(struct udevice *dev, uint offset,
+				     int value)
+{
+	uint config_offset = get_config_reg_addr(dev, offset);
+
+	pcr_clrsetbits32(dev, config_offset,
+			 PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
+				  PAD_CFG0_TX_DISABLE,
+			 PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
+				  (value ? PAD_CFG0_TX_STATE : 0));
+
+	return 0;
+}
+
+static int apl_gpio_get_function(struct udevice *dev, uint offset)
+{
+	uint mode, rx_tx;
+	u32 reg;
+
+	reg = get_config_reg(dev, offset);
+	mode = (reg & PAD_CFG0_MODE_MASK) >> PAD_CFG0_MODE_SHIFT;
+	if (!mode) {
+		rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE);
+		if (rx_tx == PAD_CFG0_TX_DISABLE)
+			return GPIOF_INPUT;
+		else if (rx_tx == PAD_CFG0_RX_DISABLE)
+			return GPIOF_OUTPUT;
+	}
+
+	return GPIOF_FUNC;
+}
+
+static int apl_gpio_get_value(struct udevice *dev, uint offset)
+{
+	uint mode, rx_tx;
+	u32 reg;
+
+	reg = get_config_reg(dev, offset);
+	mode = (reg & PAD_CFG0_MODE_MASK) >> PAD_CFG0_MODE_SHIFT;
+	if (!mode) {
+		rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE);
+		if (rx_tx == PAD_CFG0_TX_DISABLE)
+			return mode & PAD_CFG0_RX_STATE_BIT ? 1 : 0;
+		else if (rx_tx == PAD_CFG0_RX_DISABLE)
+			return mode & PAD_CFG0_TX_STATE_BIT ? 1 : 0;
+	}
+
+	return 0;
+}
+
+int gpio_route_gpe(struct udevice *itss, uint gpe0b, uint gpe0c, uint gpe0d)
+{
+	struct udevice *gpio_dev;
+	u32 misccfg_value;
+	u32 misccfg_clr;
+	int ret;
+
+	/* Get the group here for community specific MISCCFG register.
+	 * If any of these returns -1 then there is some error in devicetree
+	 * where the group is probably hardcoded and does not comply with the
+	 * PMC group defines. So we return from here and MISCFG is set to
+	 * default.
+	 */
+	ret = irq_route_pmc_gpio_gpe(itss, gpe0b);
+	if (ret)
+		return ret;
+	gpe0b = ret;
+
+	ret = irq_route_pmc_gpio_gpe(itss, gpe0c);
+	if (ret)
+		return ret;
+	gpe0c = ret;
+
+	ret = irq_route_pmc_gpio_gpe(itss, gpe0d);
+	if (ret)
+		return ret;
+	gpe0d = ret;
+
+	misccfg_value = gpe0b << MISCCFG_GPE0_DW0_SHIFT;
+	misccfg_value |= gpe0c << MISCCFG_GPE0_DW1_SHIFT;
+	misccfg_value |= gpe0d << MISCCFG_GPE0_DW2_SHIFT;
+
+	/* Program GPIO_MISCCFG */
+	misccfg_clr = MISCCFG_GPE0_DW2_MASK | MISCCFG_GPE0_DW1_MASK |
+		MISCCFG_GPE0_DW0_MASK;
+
+	log_debug("misccfg_clr:%x misccfg_value:%x\n", misccfg_clr,
+		  misccfg_value);
+	uclass_foreach_dev_probe(UCLASS_GPIO, gpio_dev) {
+		pcr_clrsetbits32(gpio_dev, GPIO_MISCCFG, misccfg_clr,
+				 misccfg_value);
+	}
+
+	return 0;
+}
+
+int gpio_gpi_clear_int_cfg(void)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_GPIO, &uc);
+	if (ret)
+		return log_msg_ret("gpio uc", ret);
+	uclass_foreach_dev(dev, uc) {
+		struct apl_gpio_platdata *plat = dev_get_platdata(dev);
+		const struct pad_community *comm = plat->comm;
+		uint sts_value;
+		int group;
+
+		for (group = 0; group < comm->num_gpi_regs; group++) {
+			/* Clear the enable register */
+			pcr_write32(dev, GPI_IE_OFFSET(comm, group), 0);
+
+			/* Read and clear the set status register bits*/
+			sts_value = pcr_read32(dev,
+					       GPI_IS_OFFSET(comm, group));
+			pcr_write32(dev, GPI_IS_OFFSET(comm, group), sts_value);
+		}
+	}
+
+	return 0;
+}
+
+int gpio_config_pads(struct udevice *dev, int num_cfgs, u32 *pads,
+		     int pads_count)
+{
+	const u32 *ptr;
+	int i;
+
+	log_debug("%s: pads_count=%d\n", __func__, pads_count);
+	for (ptr = pads, i = 0; i < pads_count; ptr += 1 + num_cfgs, i++) {
+		struct udevice *pad_dev = NULL;
+		struct pad_config *cfg;
+		int ret;
+
+		cfg = (struct pad_config *)ptr;
+		ret = gpio_get_device(cfg->pad, &pad_dev);
+		if (ret)
+			return ret;
+		ret = gpio_configure_pad(pad_dev, cfg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int apl_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+	struct apl_gpio_platdata *plat = dev_get_platdata(dev);
+	struct apl_gpio_priv *priv = dev_get_priv(dev);
+	struct p2sb_child_platdata *pplat;
+	int ret;
+	int i;
+
+	plat->num_cfgs = 2;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	/*
+	 * It would be nice to do this in the bind() method, but with
+	 * of-platdata binding happens in the order that DM finds things in the
+	 * linker list (i.e. alphabetical order by driver name). So the GPIO
+	 * device may well be bound before its parent (p2sb), and this call
+	 * will fail if p2sb is not bound yet.
+	 *
+	 * TODO(sjg at chromium.org): Add a parent pointer to child devices in dtoc
+	 */
+	ret = p2sb_set_port_id(dev, plat->dtplat.intel_p2sb_port_id);
+	if (ret)
+		return log_msg_ret("Could not set port id", ret);
+#endif
+	/* Attach this device to its community structure */
+	pplat = dev_get_parent_platdata(dev);
+	for (i = 0; i < ARRAY_SIZE(apl_gpio_communities); i++) {
+		if (apl_gpio_communities[i].port == pplat->pid)
+			plat->comm = &apl_gpio_communities[i];
+	}
+	if (!plat->comm) {
+		log_err("Cannot find community for pid %d\n", pplat->pid);
+		return -EDOM;
+	}
+	ret = uclass_first_device_err(UCLASS_IRQ, &priv->itss);
+	if (ret)
+		return log_msg_ret("Cannot find ITSS", ret);
+
+	return 0;
+}
+
+static int apl_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *upriv = dev_get_uclass_priv(dev);
+	struct apl_gpio_platdata *plat = dev_get_platdata(dev);
+	struct apl_gpio_priv *priv = dev_get_priv(dev);
+	const struct pad_community *comm = plat->comm;
+
+	upriv->gpio_count = comm->last_pad - comm->first_pad + 1;
+	upriv->bank_name = dev->name;
+	priv->itss_pol_cfg = true;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops apl_gpio_ops = {
+	.get_function	= apl_gpio_get_function,
+	.get_value	= apl_gpio_get_value,
+	.direction_input = apl_gpio_direction_input,
+	.direction_output = apl_gpio_direction_output,
+};
+
+static const struct udevice_id apl_gpio_ids[] = {
+	{ .compatible = "intel,apl-gpio"},
+	{ }
+};
+
+U_BOOT_DRIVER(apl_gpio_drv) = {
+	.name		= "intel_apl_gpio",
+	.id		= UCLASS_GPIO,
+	.of_match	= apl_gpio_ids,
+	.probe		= apl_gpio_probe,
+	.ops		= &apl_gpio_ops,
+	.ofdata_to_platdata = apl_gpio_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct apl_gpio_priv),
+	.platdata_auto_alloc_size = sizeof(struct apl_gpio_platdata),
+};
diff --git a/arch/x86/include/asm/arch-apollolake/gpio.h b/arch/x86/include/asm/arch-apollolake/gpio.h
new file mode 100644
index 00000000000..19421950e61
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/gpio.h
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot gpio.h
+ */
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+/**
+ * struct pad_config - config for a pad
+ * @pad: offset of pad within community
+ * @pad_config: Pad config data corresponding to DW0, DW1, etc.
+ */
+struct pad_config {
+	int pad;
+	u32 pad_config[4];
+};
+
+#include <asm/arch/gpio_apl.h>
+
+/* GPIO community IOSF sideband clock gating */
+#define MISCCFG_GPSIDEDPCGEN	BIT(5)
+/* GPIO community RCOMP clock gating */
+#define MISCCFG_GPRCOMPCDLCGEN	BIT(4)
+/* GPIO community RTC clock gating */
+#define MISCCFG_GPRTCDLCGEN	BIT(3)
+/* GFX controller clock gating */
+#define MISCCFG_GSXSLCGEN	BIT(2)
+/* GPIO community partition clock gating */
+#define MISCCFG_GPDPCGEN	BIT(1)
+/* GPIO community local clock gating */
+#define MISCCFG_GPDLCGEN	BIT(0)
+/* Enable GPIO community power management configuration */
+#define MISCCFG_ENABLE_GPIO_PM_CONFIG (MISCCFG_GPSIDEDPCGEN | \
+	MISCCFG_GPRCOMPCDLCGEN | MISCCFG_GPRTCDLCGEN | MISCCFG_GSXSLCGEN \
+	| MISCCFG_GPDPCGEN | MISCCFG_GPDLCGEN)
+
+/*
+ * GPIO numbers may not be contiguous and instead will have a different
+ * starting pin number for each pad group.
+ */
+#define INTEL_GPP_BASE(first_of_community, start_of_group, end_of_group,\
+			group_pad_base)					\
+	{								\
+		.first_pad = (start_of_group) - (first_of_community),	\
+		.size = (end_of_group) - (start_of_group) + 1,		\
+		.acpi_pad_base = (group_pad_base),			\
+	}
+
+/*
+ * A pad base of -1 indicates that this group uses contiguous numbering
+ * and a pad base should not be used for this group.
+ */
+#define PAD_BASE_NONE	-1
+
+/* The common/default group numbering is contiguous */
+#define INTEL_GPP(first_of_community, start_of_group, end_of_group)	\
+	INTEL_GPP_BASE(first_of_community, start_of_group, end_of_group,\
+		       PAD_BASE_NONE)
+
+/**
+ * struct reset_mapping - logical to actual value for PADRSTCFG in DW0
+ *
+ * Note that the values are expected to be within the field placement of the
+ * register itself. i.e. if the reset field is at 31:30 then the values within
+ * logical and chipset should occupy 31:30.
+ */
+struct reset_mapping {
+	u32 logical;
+	u32 chipset;
+};
+
+/**
+ * struct pad_group - describes the groups within each community
+ *
+ * @first_pad: offset of first pad of the group relative to the community
+ * @size: size of the group
+ * @acpi_pad_base: starting pin number for the pads in this group when they are
+ *	used in ACPI.  This is only needed if the pins are not contiguous across
+ *	groups. Most groups will have this set to PAD_BASE_NONE and use
+ *	contiguous numbering for ACPI.
+ */
+struct pad_group {
+	int first_pad;
+	uint size;
+	int acpi_pad_base;
+};
+
+/**
+ * struct pad_community - GPIO community
+ *
+ * This describes a community, or each group within a community when multiple
+ * groups exist inside a community
+ *
+ * @name: Community name
+ * @acpi_path: ACPI path
+ * @num_gpi_regs: number of gpi registers in community
+ * @max_pads_per_group: number of pads in each group; number of pads bit-mapped
+ *	in each GPI status/en and Host Own Reg
+ * @first_pad: first pad in community
+ * @last_pad: last pad in community
+ * @host_own_reg_0: offset to Host Ownership Reg 0
+ * @gpi_int_sts_reg_0: offset to GPI Int STS Reg 0
+ * @gpi_int_en_reg_0: offset to GPI Int Enable Reg 0
+ * @gpi_smi_sts_reg_0: offset to GPI SMI STS Reg 0
+ * @gpi_smi_en_reg_0: offset to GPI SMI EN Reg 0
+ * @pad_cfg_base: offset to first PAD_GFG_DW0 Reg
+ * @gpi_status_offset: specifies offset in struct gpi_status
+ * @port: PCR Port ID
+ * @reset_map: PADRSTCFG logical to chipset mapping
+ * @num_reset_vals: number of values in @reset_map
+ * @groups; list of groups for this community
+ * @num_groups: number of groups
+ */
+struct pad_community {
+	const char *name;
+	const char *acpi_path;
+	size_t num_gpi_regs;
+	size_t max_pads_per_group;
+	uint first_pad;
+	uint last_pad;
+	u16 host_own_reg_0;
+	u16 gpi_int_sts_reg_0;
+	u16 gpi_int_en_reg_0;
+	u16 gpi_smi_sts_reg_0;
+	u16 gpi_smi_en_reg_0;
+	u16 pad_cfg_base;
+	u8 gpi_status_offset;
+	u8 port;
+	const struct reset_mapping *reset_map;
+	size_t num_reset_vals;
+	const struct pad_group *groups;
+	size_t num_groups;
+};
+
+/**
+ * gpio_route_gpe() - set the GPIO groups for the general-purpose-event blocks
+ *
+ * The values from PMC register GPE_CFG are passed which is then mapped to
+ * proper groups for MISCCFG. This basically sets the MISCCFG register bits:
+ *  dw0 = gpe0_route[11:8]. This is ACPI GPE0b.
+ *  dw1 = gpe0_route[15:12]. This is ACPI GPE0c.
+ *  dw2 = gpe0_route[19:16]. This is ACPI GPE0d.
+ *
+ * @dev: ITSS device
+ * @gpe0b: Value for GPE0B
+ * @gpe0c: Value for GPE0C
+ * @gpe0d: Value for GPE0D
+ * @return 0 if OK, -ve on error
+ */
+int gpio_route_gpe(struct udevice *dev, uint gpe0b, uint gpe0c, uint gpe0d);
+
+/**
+ * gpio_config_pads() - Configure a list of pads
+ *
+ * Configures multiple pads using the provided data from the device tree.
+ *
+ * @dev: GPIO device (any will do)
+ * @num_cfgs: Number of configuration words for each pad (e.g. 2)
+ * @pads: Pad data, consisting of a pad number followed by @num_cfgs entries
+ *	containing the data for that pad
+ * @pads_count: Number of pads to configure
+ * @return 0 if OK, -ve on error
+ */
+int gpio_config_pads(struct udevice *dev, int num_cfgs, u32 *pads,
+		     int pads_count);
+
+/**
+ * gpio_gpi_clear_int_cfg() - Set up the interrupts for use
+ *
+ * This enables the interrupt inputs and clears the status register bits
+ *
+ * @return 0 if OK, -ve on error
+ */
+int gpio_gpi_clear_int_cfg(void);
+
+#endif
diff --git a/arch/x86/include/asm/arch-apollolake/gpio_apl.h b/arch/x86/include/asm/arch-apollolake/gpio_apl.h
new file mode 100644
index 00000000000..0706a5a34a9
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/gpio_apl.h
@@ -0,0 +1,491 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Definitions for the GPIO subsystem on Apollolake
+ *
+ * Placed in a separate file since some of these definitions can be used from
+ * assembly code
+ *
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 - 2017 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_APOLLOLAKE_GPIO_H_
+#define _SOC_APOLLOLAKE_GPIO_H_
+
+/*
+ * Miscellaneous Configuration register(MISCCFG).These are community-specific
+ * registers and are meant to house miscellaneous configuration fields per
+ * community. There are 8 GPIO groups: GPP_0 -> GPP_8 (Group 3 is absent)
+ */
+#define GPIO_MISCCFG		0x10 /* Miscellaneous Configuration offset */
+#define  GPIO_GPE_SW_31_0	0 /* SOUTHWEST GPIO#  0 ~ 31 belong to GROUP0 */
+#define  GPIO_GPE_SW_63_32	1 /* SOUTHWEST GPIO# 32 ~ 42 belong to GROUP1 */
+#define  GPIO_GPE_W_31_0	2 /* WEST      GPIO#  0 ~ 25 belong to GROUP2 */
+#define  GPIO_GPE_NW_31_0	4 /* NORTHWEST GPIO#  0 ~ 17 belong to GROUP4 */
+#define  GPIO_GPE_NW_63_32	5 /* NORTHWEST GPIO# 32 ~ 63 belong to GROUP5 */
+#define  GPIO_GPE_NW_95_64	6 /* NORTHWEST GPIO# 64 ~ 76 belong to GROUP6 */
+#define  GPIO_GPE_N_31_0	7 /* NORTH     GPIO#  0 ~ 31 belong to GROUP7 */
+#define  GPIO_GPE_N_63_32	8 /* NORTH     GPIO# 32 ~ 61 belong to GROUP8 */
+
+#define GPIO_MAX_NUM_PER_GROUP	32
+
+/* Host Software Pad Ownership Register.
+ * The pins in the community are divided into 3 groups :
+ * GPIO 0 ~ 31, GPIO 32 ~ 63, GPIO 64 ~ 95
+ */
+#define HOSTSW_OWN_REG_0		0x80
+
+#define PAD_CFG_BASE			0x500
+
+#define GPI_INT_STS_0			0x100
+#define GPI_INT_EN_0			0x110
+
+#define GPI_SMI_STS_0			0x140
+#define GPI_SMI_EN_0			0x150
+
+#define NUM_N_PADS			(PAD_N(SVID0_CLK) + 1)
+#define NUM_NW_PADS			(PAD_NW(GPIO_123) + 1)
+#define NUM_W_PADS			(PAD_W(SUSPWRDNACK) + 1)
+#define NUM_SW_PADS			(PAD_SW(LPC_FRAMEB) + 1)
+
+#define NUM_N_GPI_REGS	\
+	(ALIGN(NUM_N_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_NW_GPI_REGS	\
+	(ALIGN(NUM_NW_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_W_GPI_REGS	\
+	(ALIGN(NUM_W_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_SW_GPI_REGS	\
+	(ALIGN(NUM_SW_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+/*
+ * Total number of GPI status registers across all GPIO communities in the SOC
+ */
+#define NUM_GPI_STATUS_REGS		(NUM_N_GPI_REGS + NUM_NW_GPI_REGS \
+					+ NUM_W_GPI_REGS + NUM_SW_GPI_REGS)
+
+/* North community pads */
+#define GPIO_0				0
+#define GPIO_1				1
+#define GPIO_2				2
+#define GPIO_3				3
+#define GPIO_4				4
+#define GPIO_5				5
+#define GPIO_6				6
+#define GPIO_7				7
+#define GPIO_8				8
+#define GPIO_9				9
+#define GPIO_10				10
+#define GPIO_11				11
+#define GPIO_12				12
+#define GPIO_13				13
+#define GPIO_14				14
+#define GPIO_15				15
+#define GPIO_16				16
+#define GPIO_17				17
+#define GPIO_18				18
+#define GPIO_19				19
+#define GPIO_20				20
+#define GPIO_21				21
+#define GPIO_22				22
+#define GPIO_23				23
+#define GPIO_24				24
+#define GPIO_25				25
+#define GPIO_26				26
+#define GPIO_27				27
+#define GPIO_28				28
+#define GPIO_29				29
+#define GPIO_30				30
+#define GPIO_31				31
+#define GPIO_32				32
+#define GPIO_33				33
+#define GPIO_34				34
+#define GPIO_35				35
+#define GPIO_36				36
+#define GPIO_37				37
+#define GPIO_38				38
+#define GPIO_39				39
+#define GPIO_40				40
+#define GPIO_41				41
+#define GPIO_42				42
+#define GPIO_43				43
+#define GPIO_44				44
+#define GPIO_45				45
+#define GPIO_46				46
+#define GPIO_47				47
+#define GPIO_48				48
+#define GPIO_49				49
+#define GPIO_62				50
+#define GPIO_63				51
+#define GPIO_64				52
+#define GPIO_65				53
+#define GPIO_66				54
+#define GPIO_67				55
+#define GPIO_68				56
+#define GPIO_69				57
+#define GPIO_70				58
+#define GPIO_71				59
+#define GPIO_72				60
+#define GPIO_73				61
+#define JTAG_TCK			62
+#define JTAG_TRST_B			63
+#define JTAG_TMS			64
+#define JTAG_TDI			65
+#define JTAG_CX_PMODE			66
+#define JTAG_CX_PREQ_B			67
+#define JTAGX				68
+#define JTAG_CX_PRDY_B			69
+#define JTAG_TDO			70
+#define CNV_BRI_DT			71
+#define CNV_BRI_RSP			72
+#define CNV_RGI_DT			73
+#define CNV_RGI_RSP			74
+#define SVID0_ALERT_B			75
+#define SVID0_DATA			76
+#define SVID0_CLK			77
+
+/* Northwest community pads */
+#define GPIO_187			78
+#define GPIO_188			79
+#define GPIO_189			80
+#define GPIO_190			81
+#define GPIO_191			82
+#define GPIO_192			83
+#define GPIO_193			84
+#define GPIO_194			85
+#define GPIO_195			86
+#define GPIO_196			87
+#define GPIO_197			88
+#define GPIO_198			89
+#define GPIO_199			90
+#define GPIO_200			91
+#define GPIO_201			92
+#define GPIO_202			93
+#define GPIO_203			94
+#define GPIO_204			95
+#define PMC_SPI_FS0			96
+#define PMC_SPI_FS1			97
+#define PMC_SPI_FS2			98
+#define PMC_SPI_RXD			99
+#define PMC_SPI_TXD			100
+#define PMC_SPI_CLK			101
+#define PMIC_PWRGOOD			102
+#define PMIC_RESET_B			103
+#define GPIO_213			104
+#define GPIO_214			105
+#define GPIO_215			106
+#define PMIC_THERMTRIP_B		107
+#define PMIC_STDBY			108
+#define PROCHOT_B			109
+#define PMIC_I2C_SCL			110
+#define PMIC_I2C_SDA			111
+#define GPIO_74				112
+#define GPIO_75				113
+#define GPIO_76				114
+#define GPIO_77				115
+#define GPIO_78				116
+#define GPIO_79				117
+#define GPIO_80				118
+#define GPIO_81				119
+#define GPIO_82				120
+#define GPIO_83				121
+#define GPIO_84				122
+#define GPIO_85				123
+#define GPIO_86				124
+#define GPIO_87				125
+#define GPIO_88				126
+#define GPIO_89				127
+#define GPIO_90				128
+#define GPIO_91				129
+#define GPIO_92				130
+#define GPIO_97				131
+#define GPIO_98				132
+#define GPIO_99				133
+#define GPIO_100			134
+#define GPIO_101			135
+#define GPIO_102			136
+#define GPIO_103			137
+#define FST_SPI_CLK_FB			138
+#define GPIO_104			139
+#define GPIO_105			140
+#define GPIO_106			141
+#define GPIO_109			142
+#define GPIO_110			143
+#define GPIO_111			144
+#define GPIO_112			145
+#define GPIO_113			146
+#define GPIO_116			147
+#define GPIO_117			148
+#define GPIO_118			149
+#define GPIO_119			150
+#define GPIO_120			151
+#define GPIO_121			152
+#define GPIO_122			153
+#define GPIO_123			154
+
+/* West community pads */
+#define GPIO_124			155
+#define GPIO_125			156
+#define GPIO_126			157
+#define GPIO_127			158
+#define GPIO_128			159
+#define GPIO_129			160
+#define GPIO_130			161
+#define GPIO_131			162
+#define GPIO_132			163
+#define GPIO_133			164
+#define GPIO_134			165
+#define GPIO_135			166
+#define GPIO_136			167
+#define GPIO_137			168
+#define GPIO_138			169
+#define GPIO_139			170
+#define GPIO_146			171
+#define GPIO_147			172
+#define GPIO_148			173
+#define GPIO_149			174
+#define GPIO_150			175
+#define GPIO_151			176
+#define GPIO_152			177
+#define GPIO_153			178
+#define GPIO_154			179
+#define GPIO_155			180
+#define GPIO_209			181
+#define GPIO_210			182
+#define GPIO_211			183
+#define GPIO_212			184
+#define OSC_CLK_OUT_0			185
+#define OSC_CLK_OUT_1			186
+#define OSC_CLK_OUT_2			187
+#define OSC_CLK_OUT_3			188
+#define OSC_CLK_OUT_4			189
+#define PMU_AC_PRESENT			190
+#define PMU_BATLOW_B			191
+#define PMU_PLTRST_B			192
+#define PMU_PWRBTN_B			193
+#define PMU_RESETBUTTON_B		194
+#define PMU_SLP_S0_B			195
+#define PMU_SLP_S3_B			196
+#define PMU_SLP_S4_B			197
+#define PMU_SUSCLK			198
+#define PMU_WAKE_B			199
+#define SUS_STAT_B			200
+#define SUSPWRDNACK			201
+
+/* Southwest community pads */
+#define GPIO_205			202
+#define GPIO_206			203
+#define GPIO_207			204
+#define GPIO_208			205
+#define GPIO_156			206
+#define GPIO_157			207
+#define GPIO_158			208
+#define GPIO_159			209
+#define GPIO_160			210
+#define GPIO_161			211
+#define GPIO_162			212
+#define GPIO_163			213
+#define GPIO_164			214
+#define GPIO_165			215
+#define GPIO_166			216
+#define GPIO_167			217
+#define GPIO_168			218
+#define GPIO_169			219
+#define GPIO_170			220
+#define GPIO_171			221
+#define GPIO_172			222
+#define GPIO_179			223
+#define GPIO_173			224
+#define GPIO_174			225
+#define GPIO_175			226
+#define GPIO_176			227
+#define GPIO_177			228
+#define GPIO_178			229
+#define GPIO_186			230
+#define GPIO_182			231
+#define GPIO_183			232
+#define SMB_ALERTB			233
+#define SMB_CLK				234
+#define SMB_DATA			235
+#define LPC_ILB_SERIRQ			236
+#define LPC_CLKOUT0			237
+#define LPC_CLKOUT1			238
+#define LPC_AD0				239
+#define LPC_AD1				240
+#define LPC_AD2				241
+#define LPC_AD3				242
+#define LPC_CLKRUNB			243
+#define LPC_FRAMEB			244
+
+/* PERST_0 not defined */
+#define GPIO_PRT0_UDEF			0xFF
+
+#define TOTAL_PADS			245
+#define N_OFFSET			GPIO_0
+#define NW_OFFSET			GPIO_187
+#define W_OFFSET			GPIO_124
+#define SW_OFFSET			GPIO_205
+
+/* Macros for translating a global pad offset to a local offset */
+#define PAD_N(pad)			(pad - N_OFFSET)
+#define PAD_NW(pad)			(pad - NW_OFFSET)
+#define PAD_W(pad)			(pad - W_OFFSET)
+#define PAD_SW(pad)			(pad - SW_OFFSET)
+
+/* Linux names of the GPIO devices */
+#define GPIO_COMM_N_NAME		"INT3452:00"
+#define GPIO_COMM_NW_NAME		"INT3452:01"
+#define GPIO_COMM_W_NAME		"INT3452:02"
+#define GPIO_COMM_SW_NAME		"INT3452:03"
+
+/* Following is used in gpio asl */
+#define GPIO_COMM_NAME			"INT3452"
+#define GPIO_COMM_0_DESC	\
+	"General Purpose Input/Output (GPIO) Controller - North"
+#define GPIO_COMM_1_DESC	\
+	"General Purpose Input/Output (GPIO) Controller - Northwest"
+#define GPIO_COMM_2_DESC	\
+	"General Purpose Input/Output (GPIO) Controller - West"
+#define GPIO_COMM_3_DESC	\
+	"General Purpose Input/Output (GPIO) Controller - Southwest"
+
+#define GPIO_COMM0_PID			PID_GPIO_N
+#define GPIO_COMM1_PID			PID_GPIO_NW
+#define GPIO_COMM2_PID			PID_GPIO_W
+#define GPIO_COMM3_PID			PID_GPIO_SW
+
+/*
+ * IOxAPIC IRQs for the GPIOs, overlap is expected as we encourage to use
+ * shared IRQ instead of direct IRQ, in case of overlapping, we can easily
+ * program one of the overlap to shared IRQ to avoid the conflict.
+ */
+
+/* NorthWest community pads */
+#define PMIC_I2C_SDA_IRQ		0x32
+#define GPIO_74_IRQ			0x33
+#define GPIO_75_IRQ			0x34
+#define GPIO_76_IRQ			0x35
+#define GPIO_77_IRQ			0x36
+#define GPIO_78_IRQ			0x37
+#define GPIO_79_IRQ			0x38
+#define GPIO_80_IRQ			0x39
+#define GPIO_81_IRQ			0x3A
+#define GPIO_82_IRQ			0x3B
+#define GPIO_83_IRQ			0x3C
+#define GPIO_84_IRQ			0x3D
+#define GPIO_85_IRQ			0x3E
+#define GPIO_86_IRQ			0x3F
+#define GPIO_87_IRQ			0x40
+#define GPIO_88_IRQ			0x41
+#define GPIO_89_IRQ			0x42
+#define GPIO_90_IRQ			0x43
+#define GPIO_91_IRQ			0x44
+#define GPIO_97_IRQ			0x49
+#define GPIO_98_IRQ			0x4A
+#define GPIO_99_IRQ			0x4B
+#define GPIO_100_IRQ			0x4C
+#define GPIO_101_IRQ			0x4D
+#define GPIO_102_IRQ			0x4E
+#define GPIO_103_IRQ			0x4F
+#define GPIO_104_IRQ			0x50
+#define GPIO_105_IRQ			0x51
+#define GPIO_106_IRQ			0x52
+#define GPIO_109_IRQ			0x54
+#define GPIO_110_IRQ			0x55
+#define GPIO_111_IRQ			0x56
+#define GPIO_112_IRQ			0x57
+#define GPIO_113_IRQ			0x58
+#define GPIO_116_IRQ			0x5B
+#define GPIO_117_IRQ			0x5C
+#define GPIO_118_IRQ			0x5D
+#define GPIO_119_IRQ			0x5E
+#define GPIO_120_IRQ			0x5F
+#define GPIO_121_IRQ			0x60
+#define GPIO_122_IRQ			0x61
+#define GPIO_123_IRQ			0x62
+
+/* North community pads */
+#define GPIO_0_IRQ			0x63
+#define GPIO_1_IRQ			0x64
+#define GPIO_2_IRQ			0x65
+#define GPIO_3_IRQ			0x66
+#define GPIO_4_IRQ			0x67
+#define GPIO_5_IRQ			0x68
+#define GPIO_6_IRQ			0x69
+#define GPIO_7_IRQ			0x6A
+#define GPIO_8_IRQ			0x6B
+#define GPIO_9_IRQ			0x6C
+#define GPIO_10_IRQ			0x6D
+#define GPIO_11_IRQ			0x6E
+#define GPIO_12_IRQ			0x6F
+#define GPIO_13_IRQ			0x70
+#define GPIO_14_IRQ			0x71
+#define GPIO_15_IRQ			0x72
+#define GPIO_16_IRQ			0x73
+#define GPIO_17_IRQ			0x74
+#define GPIO_18_IRQ			0x75
+#define GPIO_19_IRQ			0x76
+#define GPIO_20_IRQ			0x77
+#define GPIO_21_IRQ			0x32
+#define GPIO_22_IRQ			0x33
+#define GPIO_23_IRQ			0x34
+#define GPIO_24_IRQ			0x35
+#define GPIO_25_IRQ			0x36
+#define GPIO_26_IRQ			0x37
+#define GPIO_27_IRQ			0x38
+#define GPIO_28_IRQ			num_reset_vals0x39
+#define GPIO_29_IRQ			0x3A
+#define GPIO_30_IRQ			0x3B
+#define GPIO_31_IRQ			0x3C
+#define GPIO_32_IRQ			0x3D
+#define GPIO_33_IRQ			0x3E
+#define GPIO_34_IRQ			0x3F
+#define GPIO_35_IRQ			0x40
+#define GPIO_36_IRQ			0x41
+#define GPIO_37_IRQ			0x42
+#define GPIO_38_IRQ			0x43
+#define GPIO_39_IRQ			0x44
+#define GPIO_40_IRQ			0x45
+#define GPIO_41_IRQ			0x46
+#define GPIO_42_IRQ			0x47
+#define GPIO_43_IRQ			0x48
+#define GPIO_44_IRQ			0x49
+#define GPIO_45_IRQ			0x4A
+#define GPIO_46_IRQ			0x4B
+#define GPIO_47_IRQ			0x4C
+#define GPIO_48_IRQ			0x4D
+#define GPIO_49_IRQ			0x4E
+#define GPIO_62_IRQ			0x5B
+#define GPIO_63_IRQ			0x5C
+#define GPIO_64_IRQ			0x5D
+#define GPIO_65_IRQ			0x5E
+#define GPIO_66_IRQ			0x5F
+#define GPIO_67_IRQ			0x60
+#define GPIO_68_IRQ			0x61
+#define GPIO_69_IRQ			0x62
+#define GPIO_70_IRQ			0x63
+#define GPIO_71_IRQ			0x64
+#define GPIO_72_IRQ			0x65
+#define GPIO_73_IRQ			0x66
+
+/*
+ * Number of PAD config registers in the Soc that have DW0 and DW1. It should
+ * be 2.
+ */
+#define GPIO_NUM_PAD_CFG_REGS   2 /* DW0, DW1 */
+
+#endif /* _SOC_APOLLOLAKE_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-apollolake/gpio_defs.h b/arch/x86/include/asm/arch-apollolake/gpio_defs.h
new file mode 100644
index 00000000000..5f8ab71ab47
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/gpio_defs.h
@@ -0,0 +1,398 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot gpio_defs.h
+ */
+
+#ifndef _ASM_ARCH_GPIO_DEFS_H_
+#define _ASM_ARCH_GPIO_DEFS_H_
+
+/* Port ids */
+#if IS_ENABLED(CONFIG_SOC_INTEL_GLK)
+#define PID_GPIO_AUDIO	0xC9
+#define PID_GPIO_SCC	0xC8
+#else
+#define PID_GPIO_SW	0xC0
+#define PID_GPIO_S	0xC2
+#define PID_GPIO_W	0xC7
+#endif
+#define PID_GPIO_NW	0xC4
+#define PID_GPIO_N	0xC5
+#define PID_ITSS	0xD0
+#define PID_RTC		0xD1
+
+#define PAD_CFG0_TX_STATE_BIT		0
+#define PAD_CFG0_TX_STATE		(1 << PAD_CFG0_TX_STATE_BIT)
+#define PAD_CFG0_RX_STATE_BIT		1
+#define PAD_CFG0_RX_STATE		(1 << PAD_CFG0_RX_STATE_BIT)
+#define PAD_CFG0_TX_DISABLE		(1 << 8)
+#define PAD_CFG0_RX_DISABLE		(1 << 9)
+
+#define PAD_CFG0_MODE_SHIFT		10
+#define PAD_CFG0_MODE_MASK		(7 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_GPIO		(0 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_NF1		(1 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_NF2		(2 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_NF3		(3 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_NF4		(4 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_NF5		(5 << PAD_CFG0_MODE_SHIFT)
+#define  PAD_CFG0_MODE_NF6		(6 << PAD_CFG0_MODE_SHIFT)
+
+#define PAD_CFG0_ROUTE_MASK		(0xf << 17)
+#define  PAD_CFG0_ROUTE_NMI		(1 << 17)
+#define  PAD_CFG0_ROUTE_SMI		(1 << 18)
+#define  PAD_CFG0_ROUTE_SCI		(1 << 19)
+#define  PAD_CFG0_ROUTE_IOAPIC		(1 << 20)
+#define PAD_CFG0_RXTENCFG_MASK		(3 << 21)
+#define PAD_CFG0_RXINV_MASK		(1 << 23)
+#define  PAD_CFG0_RX_POL_INVERT		(1 << 23)
+#define  PAD_CFG0_RX_POL_NONE		(0 << 23)
+#define  PAD_CFG0_PREGFRXSEL		(1 << 24)
+#define PAD_CFG0_TRIG_MASK		(3 << 25)
+#define  PAD_CFG0_TRIG_LEVEL		(0 << 25)
+#define  PAD_CFG0_TRIG_EDGE_SINGLE	(1 << 25) /* controlled by RX_INVERT*/
+#define  PAD_CFG0_TRIG_OFF		(2 << 25)
+#define  PAD_CFG0_TRIG_EDGE_BOTH	(3 << 25)
+#define PAD_CFG0_RXRAW1_MASK		(1 << 28)
+#define PAD_CFG0_RXPADSTSEL_MASK	(1 << 29)
+#define PAD_CFG0_RESET_MASK		(3 << 30)
+#define  PAD_CFG0_LOGICAL_RESET_PWROK	(0U << 30)
+#define  PAD_CFG0_LOGICAL_RESET_DEEP	(1U << 30)
+#define  PAD_CFG0_LOGICAL_RESET_PLTRST	(2U << 30)
+#define  PAD_CFG0_LOGICAL_RESET_RSMRST	(3U << 30)
+
+/*
+ * Use the fourth bit in IntSel field to indicate gpio ownership. This field is
+ * RO and hence not used during gpio configuration.
+ */
+#define PAD_CFG1_GPIO_DRIVER		(0x1 << 4)
+#define PAD_CFG1_IRQ_MASK		(0xff << 0)
+#define PAD_CFG1_IOSTERM_MASK		(0x3 << 8)
+#define PAD_CFG1_IOSTERM_SAME		(0x0 << 8)
+#define PAD_CFG1_IOSTERM_DISPUPD	(0x1 << 8)
+#define PAD_CFG1_IOSTERM_ENPD		(0x2 << 8)
+#define PAD_CFG1_IOSTERM_ENPU		(0x3 << 8)
+#define PAD_CFG1_PULL_MASK		(0xf << 10)
+#define  PAD_CFG1_PULL_NONE		(0x0 << 10)
+#define  PAD_CFG1_PULL_DN_5K		(0x2 << 10)
+#define  PAD_CFG1_PULL_DN_20K		(0x4 << 10)
+#define  PAD_CFG1_PULL_UP_1K		(0x9 << 10)
+#define  PAD_CFG1_PULL_UP_5K		(0xa << 10)
+#define  PAD_CFG1_PULL_UP_2K		(0xb << 10)
+#define  PAD_CFG1_PULL_UP_20K		(0xc << 10)
+#define  PAD_CFG1_PULL_UP_667		(0xd << 10)
+#define  PAD_CFG1_PULL_NATIVE		(0xf << 10)
+
+/* Tx enabled driving last value driven, Rx enabled */
+#define PAD_CFG1_IOSSTATE_TX_LAST_RXE	(0x0 << 14)
+/*
+ * Tx enabled driving 0, Rx disabled and Rx driving 0 back to its controller
+ * internally
+ */
+#define PAD_CFG1_IOSSTATE_TX0_RX_DCR_X0	(0x1 << 14)
+/*
+ * Tx enabled driving 0, Rx disabled and Rx driving 1 back to its controller
+ * internally
+ */
+#define PAD_CFG1_IOSSTATE_TX0_RX_DCR_X1	(0x2 << 14)
+/*
+ * Tx enabled driving 1, Rx disabled and Rx driving 0 back to its controller
+ * internally
+ */
+#define PAD_CFG1_IOSSTATE_TX1_RX_DCR_X0	(0x3 << 14)
+/*
+ * Tx enabled driving 1, Rx disabled and Rx driving 1 back to its controller
+ * internally
+ */
+#define PAD_CFG1_IOSSTATE_TX1_RX_DCR_X1	(0x4 << 14)
+/* Tx enabled driving 0, Rx enabled */
+#define PAD_CFG1_IOSSTATE_TX0_RXE	(0x5 << 14)
+/* Tx enabled driving 1, Rx enabled */
+#define PAD_CFG1_IOSSTATE_TX1_RXE	(0x6 << 14)
+/* Hi-Z, Rx driving 0 back to its controller internally */
+#define PAD_CFG1_IOSSTATE_HIZCRX0	(0x7 << 14)
+/* Hi-Z, Rx driving 1 back to its controller internally */
+#define PAD_CFG1_IOSSTATE_HIZCRX1	(0x8 << 14)
+/* Tx disabled, Rx enabled */
+#define PAD_CFG1_IOSSTATE_TXD_RXE	(0x9 << 14)
+#define PAD_CFG1_IOSSTATE_IGNORE	(0xf << 14) /* Ignore Iostandby */
+/* mask to extract Iostandby bits */
+#define PAD_CFG1_IOSSTATE_MASK		(0xf << 14)
+#define PAD_CFG1_IOSSTATE_SHIFT		14 /* set Iostandby bits [17:14] */
+
+#define PAD_CFG2_DEBEN			1
+/* Debounce Duration = (2 ^ PAD_CFG2_DEBOUNCE_x_RTC) * RTC clock duration */
+#define PAD_CFG2_DEBOUNCE_8_RTC		(0x3 << 1)
+#define PAD_CFG2_DEBOUNCE_16_RTC	(0x4 << 1)
+#define PAD_CFG2_DEBOUNCE_32_RTC	(0x5 << 1)
+#define PAD_CFG2_DEBOUNCE_64_RTC	(0x6 << 1)
+#define PAD_CFG2_DEBOUNCE_128_RTC	(0x7 << 1)
+#define PAD_CFG2_DEBOUNCE_256_RTC	(0x8 << 1)
+#define PAD_CFG2_DEBOUNCE_512_RTC	(0x9 << 1)
+#define PAD_CFG2_DEBOUNCE_1K_RTC	(0xa << 1)
+#define PAD_CFG2_DEBOUNCE_2K_RTC	(0xb << 1)
+#define PAD_CFG2_DEBOUNCE_4K_RTC	(0xc << 1)
+#define PAD_CFG2_DEBOUNCE_8K_RTC	(0xd << 1)
+#define PAD_CFG2_DEBOUNCE_16K_RTC	(0xe << 1)
+#define PAD_CFG2_DEBOUNCE_32K_RTC	(0xf << 1)
+#define PAD_CFG2_DEBOUNCE_MASK		0x1f
+
+/* voltage tolerance  0=3.3V default 1=1.8V tolerant */
+#if IS_ENABLED(INTEL_COMMON_GPIO_IOSTANDBY)
+#define PAD_CFG1_TOL_MASK		(0x1 << 25)
+#define  PAD_CFG1_TOL_1V8		(0x1 << 25)
+#endif
+
+#define PAD_FUNC(value)		PAD_CFG0_MODE_##value
+#define PAD_RESET(value)	PAD_CFG0_LOGICAL_RESET_##value
+#define PAD_PULL(value)		PAD_CFG1_PULL_##value
+
+#define PAD_IOSSTATE(value)	PAD_CFG1_IOSSTATE_##value
+#define PAD_IOSTERM(value)	PAD_CFG1_IOSTERM_##value
+
+#define PAD_IRQ_CFG(route, trig, inv) \
+				(PAD_CFG0_ROUTE_##route | \
+				PAD_CFG0_TRIG_##trig | \
+				PAD_CFG0_RX_POL_##inv)
+
+#if IS_ENABLED(INTEL_GPIO_DUAL_ROUTE_SUPPORT)
+#define PAD_IRQ_CFG_DUAL_ROUTE(route1, route2, trig, inv)  \
+				(PAD_CFG0_ROUTE_##route1 | \
+				PAD_CFG0_ROUTE_##route2 | \
+				PAD_CFG0_TRIG_##trig | \
+				PAD_CFG0_RX_POL_##inv)
+#endif /* CONFIG_INTEL_GPIO_DUAL_ROUTE_SUPPORT */
+
+#define _PAD_CFG_STRUCT(__pad, __config0, __config1)	\
+		__pad(__config0) (__config1)
+
+#if GPIO_NUM_PAD_CFG_REGS > 2
+#define _PAD_CFG_STRUCT_3(__pad, __config0, __config1, __config2)	\
+	{					\
+		.pad = __pad,			\
+		.pad_config[0] = __config0,	\
+		.pad_config[1] = __config1,	\
+		.pad_config[2] = __config2,	\
+	}
+#else
+#define _PAD_CFG_STRUCT_3(__pad, __config0, __config1, __config2)	\
+	_PAD_CFG_STRUCT(__pad, __config0, __config1)
+#endif
+
+/* Native function configuration */
+#define PAD_CFG_NF(pad, pull, rst, func) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TX_LAST_RXE))
+
+#if IS_ENABLED(CONFIG_INTEL_GPIO_PADCFG_PADTOL)
+/*
+ * Native 1.8V tolerant pad, only applies to some pads like I2C/I2S. Not
+ * applicable to all SOCs. Refer EDS.
+ */
+#define PAD_CFG_NF_1V8(pad, pull, rst, func) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) |\
+		PAD_IOSSTATE(TX_LAST_RXE) | PAD_CFG1_TOL_1V8)
+#endif
+
+/* Native function configuration for standby state */
+#define PAD_CFG_NF_IOSSTATE(pad, pull, rst, func, iosstate) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
+		PAD_IOSSTATE(iosstate))
+
+/*
+ * Native function configuration for standby state, also configuring iostandby
+ * as masked
+ */
+#define PAD_CFG_NF_IOSTANDBY_IGNORE(pad, pull, rst, func) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
+		PAD_IOSSTATE(IGNORE))
+
+/*
+ * Native function configuration for standby state, also configuring iosstate
+ * and iosterm
+ */
+#define PAD_CFG_NF_IOSSTATE_IOSTERM(pad, pull, rst, func, iosstate, iosterm) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
+		PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
+
+/* General purpose output, no pullup/down */
+#define PAD_CFG_GPO(pad, val, rst)	\
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
+		PAD_PULL(NONE) | PAD_IOSSTATE(TX_LAST_RXE))
+
+/* General purpose output, with termination specified */
+#define PAD_CFG_TERM_GPO(pad, val, pull, rst)	\
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
+		PAD_PULL(pull) | PAD_IOSSTATE(TX_LAST_RXE))
+
+/* General purpose output, no pullup/down */
+#define PAD_CFG_GPO_GPIO_DRIVER(pad, val, rst, pull)	\
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
+		PAD_PULL(pull) | PAD_IOSSTATE(TX_LAST_RXE) | \
+			PAD_CFG1_GPIO_DRIVER)
+
+/* General purpose output */
+#define PAD_CFG_GPO_IOSSTATE_IOSTERM(pad, val, rst, pull, iosstate, ioterm) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
+		PAD_PULL(pull) | PAD_IOSSTATE(iosstate) | PAD_IOSTERM(ioterm))
+
+/* General purpose input */
+#define PAD_CFG_GPI(pad, pull, rst) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE, \
+		PAD_PULL(pull) | PAD_IOSSTATE(TXD_RXE))
+
+/* General purpose input. The following macro sets the
+ * Host Software Pad Ownership to GPIO Driver mode.
+ */
+#define PAD_CFG_GPI_GPIO_DRIVER(pad, pull, rst) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE, \
+		PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TXD_RXE))
+
+#define PAD_CFG_GPIO_DRIVER_HI_Z(pad, pull, rst, iosstate, iosterm) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE |	\
+		PAD_CFG0_RX_DISABLE,					\
+		PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER |			\
+		PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
+
+#define PAD_CFG_GPIO_HI_Z(pad, pull, rst, iosstate, iosterm) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE |	\
+		PAD_CFG0_RX_DISABLE, PAD_PULL(pull) |			\
+		PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
+
+/* GPIO Interrupt */
+#define PAD_CFG_GPI_INT(pad, pull, rst, trig) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE |	\
+			PAD_CFG0_TRIG_##trig | PAD_CFG0_RX_POL_NONE,	\
+		PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TXD_RXE))
+
+/*
+ * No Connect configuration for unused pad.
+ * Both TX and RX are disabled. RX disabling is done to avoid unnecessary
+ * setting of GPI_STS.
+ */
+#define PAD_NC(pad, pull)			\
+	_PAD_CFG_STRUCT(pad,					\
+		PAD_FUNC(GPIO) | PAD_RESET(DEEP) |		\
+		PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE,	\
+		PAD_PULL(pull) | PAD_IOSSTATE(TXD_RXE))
+
+/* General purpose input, routed to APIC */
+#define PAD_CFG_GPI_APIC(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(IOAPIC, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TXD_RXE))
+
+/* General purpose input, routed to APIC - with IOStandby Config*/
+#define PAD_CFG_GPI_APIC_IOS(pad, pull, rst, trig, inv, iosstate, iosterm) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(IOAPIC, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
+
+/*
+ * The following APIC macros assume the APIC will handle the filtering
+ * on its own end. One just needs to pass an active high message into the
+ * ITSS.
+ */
+#define PAD_CFG_GPI_APIC_LOW(pad, pull, rst) \
+	PAD_CFG_GPI_APIC(pad, pull, rst, LEVEL, INVERT)
+
+#define PAD_CFG_GPI_APIC_HIGH(pad, pull, rst) \
+	PAD_CFG_GPI_APIC(pad, pull, rst, LEVEL, NONE)
+
+#define PAD_CFG_GPI_APIC_EDGE_LOW(pad, pull, rst) \
+	PAD_CFG_GPI_APIC(pad, pull, rst, EDGE_SINGLE, INVERT)
+
+/* General purpose input, routed to SMI */
+#define PAD_CFG_GPI_SMI(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SMI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TXD_RXE))
+
+/* General purpose input, routed to SMI */
+#define PAD_CFG_GPI_SMI_IOS(pad, pull, rst, trig, inv, iosstate, iosterm) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SMI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
+
+#define PAD_CFG_GPI_SMI_LOW(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SMI(pad, pull, rst, trig, INVERT)
+
+#define PAD_CFG_GPI_SMI_HIGH(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SMI(pad, pull, rst, trig, NONE)
+
+/* General purpose input, routed to SCI */
+#define PAD_CFG_GPI_SCI(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TXD_RXE))
+
+/* General purpose input, routed to SCI */
+#define PAD_CFG_GPI_SCI_IOS(pad, pull, rst, trig, inv, iosstate, iosterm) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
+
+#define PAD_CFG_GPI_SCI_LOW(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SCI(pad, pull, rst, trig, INVERT)
+
+#define PAD_CFG_GPI_SCI_HIGH(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SCI(pad, pull, rst, trig, NONE)
+
+#define PAD_CFG_GPI_SCI_DEBEN(pad, pull, rst, trig, inv, dur) \
+	_PAD_CFG_STRUCT_3(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TXD_RXE), PAD_CFG2_DEBEN | PAD_CFG2_##dur)
+
+#define PAD_CFG_GPI_SCI_LOW_DEBEN(pad, pull, rst, trig, dur) \
+	PAD_CFG_GPI_SCI_DEBEN(pad, pull, rst, trig, INVERT, dur)
+
+#define PAD_CFG_GPI_SCI_HIGH_DEBEN(pad, pull, rst, trig, dur) \
+	PAD_CFG_GPI_SCI_DEBEN(pad, pull, rst, trig, NONE, dur)
+
+/* General purpose input, routed to NMI */
+#define PAD_CFG_GPI_NMI(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(NMI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TXD_RXE))
+
+#if IS_ENABLED(INTEL_GPIO_DUAL_ROUTE_SUPPORT)
+/* GPI, GPIO Driver, SCI interrupt */
+#define PAD_CFG_GPI_GPIO_DRIVER_SCI(pad, pull, rst, trig, inv)	\
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+			PAD_IRQ_CFG(SCI, trig, inv),	\
+		PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TXD_RXE))
+
+#define PAD_CFG_GPI_DUAL_ROUTE(pad, pull, rst, trig, inv, route1, route2) \
+	_PAD_CFG_STRUCT(pad,						\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG_DUAL_ROUTE(route1, route2,  trig, inv), \
+		PAD_PULL(pull) | PAD_IOSSTATE(TXD_RXE))
+
+#define PAD_CFG_GPI_IRQ_WAKE(pad, pull, rst, trig, inv)	\
+	PAD_CFG_GPI_DUAL_ROUTE(pad, pull, rst, trig, inv, IOAPIC, SCI)
+
+#endif /* CONFIG_INTEL_GPIO_DUAL_ROUTE_SUPPORT */
+
+#endif /* _ASM_ARCH_GPIO_DEFS_H_ */
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 094/108] i2c: designware: Add apollolake support
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (70 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 093/108] x86: apollolake: Add GPIO driver Simon Glass
@ 2019-10-21  3:38 ` Simon Glass
  2019-10-28  4:47   ` Heiko Schocher
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 095/108] x86: apollolake: Add systemagent driver Simon Glass
                   ` (15 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:38 UTC (permalink / raw)
  To: u-boot

For apollolake we need to take the I2C bus controller out of reset before
using this. Add this functionality to the driver.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add a weak function to avoid errors on other platforms

Changes in v2: None

 drivers/i2c/dw_i2c_pci.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/dw_i2c_pci.c b/drivers/i2c/dw_i2c_pci.c
index 065c0aa5994..d6d93f08a56 100644
--- a/drivers/i2c/dw_i2c_pci.c
+++ b/drivers/i2c/dw_i2c_pci.c
@@ -6,8 +6,14 @@
  */
 
 #include <dm.h>
+#include <asm/lpss.h>
 #include "designware_i2c.h"
 
+enum {
+	VANILLA		= 0,
+	INTEL_APL,
+};
+
 /* BayTrail HCNT/LCNT/SDA hold time */
 static struct dw_scl_sda_cfg byt_config = {
 	.ss_hcnt = 0x200,
@@ -17,6 +23,9 @@ static struct dw_scl_sda_cfg byt_config = {
 	.sda_hold = 0x6,
 };
 
+/* Have a weak function for now - possibly should be a new uclass */
+void lpss_reset_release(void *regs);
+
 static int designware_i2c_pci_probe(struct udevice *dev)
 {
 	struct dw_i2c *priv = dev_get_priv(dev);
@@ -25,9 +34,12 @@ static int designware_i2c_pci_probe(struct udevice *dev)
 	priv->regs = (struct i2c_regs *)
 		dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
 	if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
-		/* Use BayTrail specific timing values */
+		/* Use BayTrail-specific timing values */
 		priv->scl_sda_cfg = &byt_config;
 
+	if (dev_get_driver_data(dev) == INTEL_APL)
+		lpss_reset_release(priv->regs);
+
 	return designware_i2c_probe(dev);
 }
 
@@ -72,6 +84,12 @@ static struct pci_device_id designware_pci_supported[] = {
 	{ PCI_VDEVICE(INTEL, 0x0f45) },
 	{ PCI_VDEVICE(INTEL, 0x0f46) },
 	{ PCI_VDEVICE(INTEL, 0x0f47) },
+	{ PCI_VDEVICE(INTEL, 0x5aac), .driver_data = INTEL_APL },
+	{ PCI_VDEVICE(INTEL, 0x5aae), .driver_data = INTEL_APL },
+	{ PCI_VDEVICE(INTEL, 0x5ab0), .driver_data = INTEL_APL },
+	{ PCI_VDEVICE(INTEL, 0x5ab2), .driver_data = INTEL_APL },
+	{ PCI_VDEVICE(INTEL, 0x5ab4), .driver_data = INTEL_APL },
+	{ PCI_VDEVICE(INTEL, 0x5ab6), .driver_data = INTEL_APL },
 	{},
 };
 
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 095/108] x86: apollolake: Add systemagent driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (71 preceding siblings ...)
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 094/108] i2c: designware: Add apollolake support Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  8:16   ` Andy Shevchenko
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 096/108] x86: apollolake: Add hostbridge driver Simon Glass
                   ` (14 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

This driver handles communication with the systemagent which needs to be
told when U-Boot has completed its init.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/x86/cpu/apollolake/Makefile              |  2 ++
 arch/x86/cpu/apollolake/systemagent.c         | 19 ++++++++++++
 .../include/asm/arch-apollolake/systemagent.h | 31 +++++++++++++++++++
 3 files changed, 52 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/systemagent.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/systemagent.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index fa53ea10b79..351fba21298 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -2,6 +2,8 @@
 #
 # Copyright (c) 2016 Google, Inc
 
+obj-$(CONFIG_SPL_BUILD) += systemagent.o
+
 obj-y += gpio.o
 obj-y += lpss.o
 obj-y += pmc.o
diff --git a/arch/x86/cpu/apollolake/systemagent.c b/arch/x86/cpu/apollolake/systemagent.c
new file mode 100644
index 00000000000..3a41b329c3d
--- /dev/null
+++ b/arch/x86/cpu/apollolake/systemagent.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Take from coreboot project file of the same name
+ */
+
+#include <common.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/arch/systemagent.h>
+
+void enable_bios_reset_cpl(void)
+{
+	/*
+	 * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
+	 * that BIOS has initialised memory and power management
+	 */
+	setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 3);
+}
diff --git a/arch/x86/include/asm/arch-apollolake/systemagent.h b/arch/x86/include/asm/arch-apollolake/systemagent.h
new file mode 100644
index 00000000000..5983e4e6302
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/systemagent.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Take from coreboot project file of the same name
+ */
+
+#ifndef __ARCH_SYSTEMAGENT_H
+#define __ARCH_SYSTEMAGENT_H
+
+/* Device 0:0.0 PCI configuration space */
+#define MCHBAR		0x48
+
+/* RAPL Package Power Limit register under MCHBAR */
+#define PUNIT_THERMAL_DEVICE_IRQ		0x700C
+#define PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER	0x18
+#define PUINT_THERMAL_DEVICE_IRQ_LOCK		0x80000000
+#define BIOS_RESET_CPL		0x7078
+#define   PCODE_INIT_DONE	BIT(8)
+#define MCHBAR_RAPL_PPL		0x70A8
+#define CORE_DISABLE_MASK	0x7168
+#define CAPID0_A		0xE4
+#define   VTD_DISABLE		BIT(23)
+#define DEFVTBAR		0x6c80
+#define GFXVTBAR		0x6c88
+#define   VTBAR_ENABLED		0x01
+#define VTBAR_MASK		0xfffffff000ull
+#define VTBAR_SIZE		0x1000
+
+void enable_bios_reset_cpl(void);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 096/108] x86: apollolake: Add hostbridge driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (72 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 095/108] x86: apollolake: Add systemagent driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver Simon Glass
                   ` (13 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

This driver models the hostbridge as a northbridge. It simply sets up the
graphics BAR. It supports of-platdata.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Move pad programming into the hostbridge to reduce TPL device-tree size
- Use pci_get_devfn()

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile            |   1 +
 arch/x86/cpu/apollolake/hostbridge.c        | 220 ++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/gpio.h |  11 +
 3 files changed, 232 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/hostbridge.c

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 351fba21298..0615bb120d3 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_SPL_BUILD) += systemagent.o
 
 obj-y += gpio.o
+obj-y += hostbridge.o
 obj-y += lpss.o
 obj-y += pmc.o
 obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/hostbridge.c b/arch/x86/cpu/apollolake/hostbridge.c
new file mode 100644
index 00000000000..96fa71f0786
--- /dev/null
+++ b/arch/x86/cpu/apollolake/hostbridge.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <spl.h>
+#include <asm/intel_regs.h>
+#include <asm/pci.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/systemagent.h>
+
+/**
+ * struct apl_hostbridge_platdata - platform data for hostbridge
+ *
+ * @num_cfgs: Number of configuration words for each pad
+ * @early_pads: Early pad data to set up, each (pad, cfg0, cfg1)
+ * @early_pads_count: Number of pads to process
+ * @pciex_region_size: BAR length in bytes
+ * @bdf: Bus/device/function of hostbridge
+ */
+struct apl_hostbridge_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_intel_apl_hostbridge dtplat;
+#endif
+	int num_cfgs;
+	u32 *early_pads;
+	int early_pads_count;
+	uint pciex_region_size;
+	pci_dev_t bdf;
+};
+
+enum {
+	PCIEXBAR		= 0x60,
+	PCIEXBAR_LENGTH_256MB	= 0,
+	PCIEXBAR_LENGTH_128MB,
+	PCIEXBAR_LENGTH_64MB,
+
+	PCIEXBAR_PCIEXBAREN	= 1 << 0,
+
+	TSEG			= 0xb8,  /* TSEG base */
+};
+
+static int apl_hostbridge_early_init_gpio(struct udevice *dev)
+{
+	struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
+
+	return gpio_config_pads(dev, plat->num_cfgs, plat->early_pads,
+				plat->early_pads_count);
+}
+
+static int apl_hostbridge_early_init(struct udevice *dev)
+{
+	struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
+	u32 region_size;
+	ulong base;
+	u32 reg;
+	int ret;
+
+	/* Set up the MCHBAR */
+	pci_x86_read_config(plat->bdf, MCHBAR, &base, PCI_SIZE_32);
+	base = MCH_BASE_ADDRESS;
+	pci_x86_write_config(plat->bdf, MCHBAR, base | 1, PCI_SIZE_32);
+
+	/*
+	 * The PCIEXBAR is assumed to live in the memory mapped IO space under
+	 * 4GiB
+	 */
+	pci_x86_write_config(plat->bdf, PCIEXBAR + 4, 0, PCI_SIZE_32);
+
+	switch (plat->pciex_region_size >> 20) {
+	default:
+	case 256:
+		region_size = PCIEXBAR_LENGTH_256MB;
+		break;
+	case 128:
+		region_size = PCIEXBAR_LENGTH_128MB;
+		break;
+	case 64:
+		region_size = PCIEXBAR_LENGTH_64MB;
+		break;
+	}
+
+	reg = CONFIG_MMCONF_BASE_ADDRESS | (region_size << 1)
+				| PCIEXBAR_PCIEXBAREN;
+	pci_x86_write_config(plat->bdf, PCIEXBAR, reg, PCI_SIZE_32);
+
+	/*
+	 * TSEG defines the base of SMM range. BIOS determines the base
+	 * of TSEG memory which must be at or below Graphics base of GTT
+	 * Stolen memory, hence its better to clear TSEG register early
+	 * to avoid power on default non-zero value (if any).
+	 */
+	pci_x86_write_config(plat->bdf, TSEG, 0, PCI_SIZE_32);
+
+	ret = apl_hostbridge_early_init_gpio(dev);
+	if (ret)
+		return log_msg_ret("gpio", ret);
+
+	return 0;
+}
+
+static int read_pads(ofnode node, const char *prop, int num_cfgs, u32 **padsp,
+		     int *pad_countp)
+{
+	u32 *pads;
+	int size;
+	int ret;
+
+	*padsp = NULL;
+	*pad_countp = 0;
+	size = ofnode_read_size(node, prop);
+	if (size < 0)
+		return 0;
+
+	pads = malloc(size);
+	if (!pads)
+		return -ENOMEM;
+	size /= sizeof(fdt32_t);
+	ret = ofnode_read_u32_array(node, prop, pads, size);
+	if (ret) {
+		free(pads);
+		return ret;
+	}
+	*pad_countp = size / (1 + num_cfgs);
+	*padsp = pads;
+
+	return 0;
+}
+
+int hostbridge_config_pads_for_node(struct udevice *dev, ofnode node)
+{
+	struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
+	int pads_count;
+	u32 *pads;
+	int ret;
+
+	ret = read_pads(node, "pads", plat->num_cfgs, &pads, &pads_count);
+	if (ret)
+		return log_msg_ret("no pads", ret);
+	ret = gpio_config_pads(dev, plat->num_cfgs, pads, pads_count);
+	free(pads);
+	if (ret)
+		return log_msg_ret("pad config", ret);
+
+	return 0;
+}
+
+static int apl_hostbridge_ofdata_to_platdata(struct udevice *dev)
+{
+	struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
+
+	plat->num_cfgs = 2;
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	int root;
+	int ret;
+
+	/* Get length of PCI Express Region */
+	plat->pciex_region_size = dev_read_u32_default(dev, "pciex-region-size",
+						       256 << 20);
+
+	root = pci_get_devfn(dev);
+	if (root < 0)
+		return log_msg_ret("Cannot get host-bridge PCI address", root);
+	plat->bdf = root;
+	ret = read_pads(dev_ofnode(dev), "early-pads", plat->num_cfgs,
+			&plat->early_pads, &plat->early_pads_count);
+	if (ret)
+		return log_msg_ret("early-pads", ret);
+#else
+	struct dtd_intel_apl_hostbridge *dtplat = &plat->dtplat;
+	int size;
+	int i;
+
+	plat->pciex_region_size = dtplat->pciex_region_size;
+	plat->bdf = pci_x86_ofplat_get_devfn(dtplat->reg[0]);
+
+	/* Assume that if everything is 0, it is empty */
+	plat->early_pads = dtplat->early_pads;
+	size = ARRAY_SIZE(dtplat->early_pads);
+	for (i = 0; i < size;) {
+		u32 val;
+		int j;
+
+		for (val = j = 0; j < plat->num_cfgs + 1; j++)
+			val |= dtplat->early_pads[i + j];
+		if (!val)
+			break;
+		plat->early_pads_count++;
+		i += plat->num_cfgs + 1;
+	}
+
+#endif
+
+	return 0;
+}
+
+static int apl_hostbridge_probe(struct udevice *dev)
+{
+	if (spl_phase() == PHASE_TPL)
+		return apl_hostbridge_early_init(dev);
+
+	return 0;
+}
+
+static const struct udevice_id apl_hostbridge_ids[] = {
+	{ .compatible = "intel,apl-hostbridge" },
+	{ }
+};
+
+U_BOOT_DRIVER(apl_hostbridge_drv) = {
+	.name		= "intel_apl_hostbridge",
+	.id		= UCLASS_NORTHBRIDGE,
+	.of_match	= apl_hostbridge_ids,
+	.ofdata_to_platdata = apl_hostbridge_ofdata_to_platdata,
+	.probe		= apl_hostbridge_probe,
+	.platdata_auto_alloc_size = sizeof(struct apl_hostbridge_platdata),
+};
diff --git a/arch/x86/include/asm/arch-apollolake/gpio.h b/arch/x86/include/asm/arch-apollolake/gpio.h
index 19421950e61..47f87bb0142 100644
--- a/arch/x86/include/asm/arch-apollolake/gpio.h
+++ b/arch/x86/include/asm/arch-apollolake/gpio.h
@@ -177,4 +177,15 @@ int gpio_config_pads(struct udevice *dev, int num_cfgs, u32 *pads,
  */
 int gpio_gpi_clear_int_cfg(void);
 
+/**
+ * hostbridge_config_pads_for_node() - Configure GPIO pads
+ *
+ * Set up the pads using the data in a given node
+ *
+ * @dev: Hostbridge device
+ * @node: Node containing the 'pads' property with the data in it
+ * @return 0 if OK, -ve on error
+ */
+int hostbridge_config_pads_for_node(struct udevice *dev, ofnode node);
+
 #endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (73 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 096/108] x86: apollolake: Add hostbridge driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  8:41   ` Andy Shevchenko
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 098/108] x86: apollolake: Add LPC driver Simon Glass
                   ` (12 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

This driver models some sort of interrupt thingy but there are so many
abreviations that I cannot find out what it stands for. Possibly something
to do with interrupts.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add snapshot/restore for IRQs
- Use the IRQ uclass instead of ITSS

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile            |   1 +
 arch/x86/cpu/apollolake/itss.c              | 214 ++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/itss.h |  43 ++++
 3 files changed, 258 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/itss.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/itss.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 0615bb120d3..edd7e49154b 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o
 
 obj-y += gpio.o
 obj-y += hostbridge.o
+obj-y += itss.o
 obj-y += lpss.o
 obj-y += pmc.o
 obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/itss.c b/arch/x86/cpu/apollolake/itss.c
new file mode 100644
index 00000000000..8789f8e6bb9
--- /dev/null
+++ b/arch/x86/cpu/apollolake/itss.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Something to do with Interrupts, but I don't know what ITSS stands for
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ * Copyright (C) 2017 Siemens AG
+ * Copyright 2019 Google LLC
+ *
+ * Taken from coreboot itss.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <irq.h>
+#include <p2sb.h>
+#include <spl.h>
+#include <asm/arch/itss.h>
+
+struct apl_itss_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	/* Put this first since driver model will copy the data here */
+	struct dtd_intel_apl_itss dtplat;
+#endif
+};
+
+/* struct pmc_route - Routing for PMC to GPIO */
+struct pmc_route {
+	u32 pmc;
+	u32 gpio;
+};
+
+struct apl_itss_priv {
+	struct pmc_route *route;
+	uint route_count;
+	u32 irq_snapshot[NUM_IPC_REGS];
+};
+
+static int apl_set_polarity(struct udevice *dev, uint irq, bool active_low)
+{
+	u32 mask;
+	uint reg;
+
+	if (irq > ITSS_MAX_IRQ)
+		return -EINVAL;
+
+	reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * (irq / IRQS_PER_IPC);
+	mask = 1 << (irq % IRQS_PER_IPC);
+
+	pcr_clrsetbits32(dev, reg, mask, active_low ? mask : 0);
+
+	return 0;
+}
+
+#ifndef CONFIG_TPL_BUILD
+static int apl_snapshot_polarities(struct udevice *dev)
+{
+	struct apl_itss_priv *priv = dev_get_priv(dev);
+	const int start = GPIO_IRQ_START;
+	const int end = GPIO_IRQ_END;
+	int reg_start;
+	int reg_end;
+	int i;
+
+	reg_start = start / IRQS_PER_IPC;
+	reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+
+	for (i = reg_start; i < reg_end; i++) {
+		uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+
+		priv->irq_snapshot[i] = pcr_read32(dev, reg);
+	}
+
+	return 0;
+}
+
+static void show_polarities(struct udevice *dev, const char *msg)
+{
+	int i;
+
+	log_info("ITSS IRQ Polarities %s:\n", msg);
+	for (i = 0; i < NUM_IPC_REGS; i++) {
+		uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+
+		log_info("IPC%d: 0x%08x\n", i, pcr_read32(dev, reg));
+	}
+}
+
+static int apl_restore_polarities(struct udevice *dev)
+{
+	struct apl_itss_priv *priv = dev_get_priv(dev);
+	const int start = GPIO_IRQ_START;
+	const int end = GPIO_IRQ_END;
+	int reg_start;
+	int reg_end;
+	int i;
+
+	show_polarities(dev, "Before");
+
+	reg_start = start / IRQS_PER_IPC;
+	reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+
+	for (i = reg_start; i < reg_end; i++) {
+		u32 mask;
+		u16 reg;
+		int irq_start;
+		int irq_end;
+
+		irq_start = i * IRQS_PER_IPC;
+		irq_end = min(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ);
+
+		if (start > irq_end)
+			continue;
+		if (end < irq_start)
+			break;
+
+		/* Track bits within the bounds of of the register */
+		irq_start = max(start, irq_start) % IRQS_PER_IPC;
+		irq_end = min(end, irq_end) % IRQS_PER_IPC;
+
+		/* Create bitmask of the inclusive range of start and end */
+		mask = (((1U << irq_end) - 1) | (1U << irq_end));
+		mask &= ~((1U << irq_start) - 1);
+
+		reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+		pcr_clrsetbits32(dev, reg, mask, mask & priv->irq_snapshot[i]);
+	}
+
+	show_polarities(dev, "After");
+
+	return 0;
+}
+#endif
+
+static int apl_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
+{
+	struct apl_itss_priv *priv = dev_get_priv(dev);
+	struct pmc_route *route;
+	int i;
+
+	for (i = 0, route = priv->route; i < priv->route_count; i++, route++) {
+		if (pmc_gpe_num == route->pmc)
+			return route->gpio;
+	}
+
+	return -ENOENT;
+}
+
+static int apl_itss_ofdata_to_platdata(struct udevice *dev)
+{
+	struct apl_itss_priv *priv = dev_get_priv(dev);
+	int ret;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct apl_itss_platdata *plat = dev_get_platdata(dev);
+	struct dtd_intel_apl_itss *dtplat = &plat->dtplat;
+
+	/*
+	 * It would be nice to do this in the bind() method, but with
+	 * of-platdata binding happens in the order that DM finds things in the
+	 * linker list (i.e. alphabetical order by driver name). So the GPIO
+	 * device may well be bound before its parent (p2sb), and this call
+	 * will fail if p2sb is not bound yet.
+	 *
+	 * TODO(sjg at chromium.org): Add a parent pointer to child devices in dtoc
+	 */
+	ret = p2sb_set_port_id(dev, dtplat->intel_p2sb_port_id);
+	if (ret)
+		return log_msg_ret("Could not set port id", ret);
+	priv->route = (struct pmc_route *)dtplat->intel_pmc_routes;
+	priv->route_count = ARRAY_SIZE(dtplat->intel_pmc_routes) /
+		 sizeof(struct pmc_route);
+#else
+	int size;
+
+	size = dev_read_size(dev, "intel,pmc-routes");
+	if (size < 0)
+		return size;
+	priv->route = malloc(size);
+	if (!priv->route)
+		return -ENOMEM;
+	ret = dev_read_u32_array(dev, "intel,pmc-routes", (u32 *)priv->route,
+				 size / sizeof(fdt32_t));
+	if (ret)
+		return log_msg_ret("Cannot read pmc-routes", ret);
+	priv->route_count = size / sizeof(struct pmc_route);
+#endif
+
+	return 0;
+}
+
+static const struct irq_ops apl_itss_ops = {
+	.route_pmc_gpio_gpe	= apl_route_pmc_gpio_gpe,
+	.set_polarity	= apl_set_polarity,
+#ifndef CONFIG_TPL_BUILD
+	.snapshot_polarities = apl_snapshot_polarities,
+	.restore_polarities = apl_restore_polarities,
+#endif
+};
+
+static const struct udevice_id apl_itss_ids[] = {
+	{ .compatible = "intel,apl-itss"},
+	{ }
+};
+
+U_BOOT_DRIVER(apl_itss_drv) = {
+	.name		= "intel_apl_itss",
+	.id		= UCLASS_IRQ,
+	.of_match	= apl_itss_ids,
+	.ops		= &apl_itss_ops,
+	.ofdata_to_platdata = apl_itss_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct apl_itss_platdata),
+	.priv_auto_alloc_size = sizeof(struct apl_itss_priv),
+};
diff --git a/arch/x86/include/asm/arch-apollolake/itss.h b/arch/x86/include/asm/arch-apollolake/itss.h
new file mode 100644
index 00000000000..c8fbb7b19c3
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/itss.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot itss.h
+ */
+
+#ifndef ASM_ARCH_ITSS_H
+#define ASM_ARCH_ITSS_H
+
+#define GPIO_IRQ_START	50
+#define GPIO_IRQ_END	ITSS_MAX_IRQ
+
+#define ITSS_MAX_IRQ	119
+#define IRQS_PER_IPC	32
+#define NUM_IPC_REGS	((ITSS_MAX_IRQ + IRQS_PER_IPC - 1) / IRQS_PER_IPC)
+
+/* Max PXRC registers in ITSS */
+#define MAX_PXRC_CONFIG	(PCR_ITSS_PIRQH_ROUT - PCR_ITSS_PIRQA_ROUT + 1)
+
+/* PIRQA Routing Control Register */
+#define PCR_ITSS_PIRQA_ROUT	0x3100
+/* PIRQB Routing Control Register */
+#define PCR_ITSS_PIRQB_ROUT	0x3101
+/* PIRQC Routing Control Register */
+#define PCR_ITSS_PIRQC_ROUT	0x3102
+/* PIRQD Routing Control Register */
+#define PCR_ITSS_PIRQD_ROUT	0x3103
+/* PIRQE Routing Control Register */
+#define PCR_ITSS_PIRQE_ROUT	0x3104
+/* PIRQF Routing Control Register */
+#define PCR_ITSS_PIRQF_ROUT	0x3105
+/* PIRQG Routing Control Register */
+#define PCR_ITSS_PIRQG_ROUT	0x3106
+/* PIRQH Routing Control Register */
+#define PCR_ITSS_PIRQH_ROUT	0x3107
+/* ITSS Interrupt polarity control */
+#define PCR_ITSS_IPC0_CONF	0x3200
+/* ITSS Power reduction control */
+#define PCR_ITSS_ITSSPRC	0x3300
+
+#endif /* ASM_ARCH_ITSS_H */
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 098/108] x86: apollolake: Add LPC driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (74 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 099/108] x86: apollolake: Add PCH driver Simon Glass
                   ` (11 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

This driver the LPC and provides a few functions to set up LPC features.
These should probably use ioctls() or perhaps, better, have specific
uclass methods.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Drop unused code in lpc_configure_pads()
- Fix value of LPC_BC_LE

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile           |   1 +
 arch/x86/cpu/apollolake/lpc.c              | 141 +++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/lpc.h |  61 +++++++++
 3 files changed, 203 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/lpc.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/lpc.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index edd7e49154b..71c3cd08241 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o
 obj-y += gpio.o
 obj-y += hostbridge.o
 obj-y += itss.o
+obj-y += lpc.o
 obj-y += lpss.o
 obj-y += pmc.o
 obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/lpc.c b/arch/x86/cpu/apollolake/lpc.c
new file mode 100644
index 00000000000..1426b182542
--- /dev/null
+++ b/arch/x86/cpu/apollolake/lpc.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ *
+ * From coreboot apollolake support lpc.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/lpc_common.h>
+#include <asm/pci.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/lpc.h>
+#include <linux/log2.h>
+
+void lpc_configure_pads(void)
+{
+	/* All pads are configured by the hostbridge */
+}
+
+void lpc_enable_fixed_io_ranges(uint io_enables)
+{
+	pci_x86_clrset_config(PCH_DEV_LPC, LPC_IO_ENABLES, 0, io_enables,
+			      PCI_SIZE_16);
+}
+
+/*
+ * Find the first unused IO window.
+ * Returns -1 if not found, 0 for reg 0x84, 1 for reg 0x88 ...
+ */
+static int find_unused_pmio_window(void)
+{
+	int i;
+	ulong lgir;
+
+	for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) {
+		pci_x86_read_config(PCH_DEV_LPC, LPC_GENERIC_IO_RANGE(i),
+				    &lgir, PCI_SIZE_32);
+
+		if (!(lgir & LPC_LGIR_EN))
+			return i;
+	}
+
+	return -1;
+}
+
+int lpc_open_pmio_window(uint base, uint size)
+{
+	int i, lgir_reg_num;
+	u32 lgir_reg_offset, lgir, window_size, alignment;
+	ulong bridged_size, bridge_base;
+	ulong reg;
+
+	log_debug("LPC: Trying to open IO window from %x size %x\n", base,
+		  size);
+
+	bridged_size = 0;
+	bridge_base = base;
+
+	while (bridged_size < size) {
+		/* Each IO range register can only open a 256-byte window */
+		window_size = min(size, (uint)LPC_LGIR_MAX_WINDOW_SIZE);
+
+		/* Window size must be a power of two for the AMASK to work */
+		alignment = 1UL << (order_base_2(window_size));
+		window_size = ALIGN(window_size, alignment);
+
+		/* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18] */
+		lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN;
+		lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK;
+
+		/* Skip programming if same range already programmed */
+		for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) {
+			pci_x86_read_config(PCH_DEV_LPC,
+					    LPC_GENERIC_IO_RANGE(i), &reg,
+					    PCI_SIZE_32);
+			if (lgir == reg)
+				return -EALREADY;
+		}
+
+		lgir_reg_num = find_unused_pmio_window();
+		if (lgir_reg_num < 0) {
+			log_err("LPC: Cannot open IO window: %lx size %lx\n",
+				bridge_base, size - bridged_size);
+			log_err("No more IO windows\n");
+
+			return -ENOSPC;
+		}
+		lgir_reg_offset = LPC_GENERIC_IO_RANGE(lgir_reg_num);
+
+		pci_x86_write_config(PCH_DEV_LPC, lgir_reg_offset, lgir,
+				     PCI_SIZE_32);
+
+		log_debug("LPC: Opened IO window LGIR%d: base %lx size %x\n",
+			  lgir_reg_num, bridge_base, window_size);
+
+		bridged_size += window_size;
+		bridge_base += window_size;
+	}
+
+	return 0;
+}
+
+void lpc_io_setup_comm_a_b(void)
+{
+	/* ComA Range 3F8h-3FFh [2:0] */
+	u16 com_ranges = LPC_IOD_COMA_RANGE;
+	u16 com_enable = LPC_IOE_COMA_EN;
+
+	/* ComB Range 2F8h-2FFh [6:4] */
+	if (0) {
+		com_ranges |= LPC_IOD_COMB_RANGE;
+		com_enable |= LPC_IOE_COMB_EN;
+	}
+
+	/* Setup I/O Decode Range Register for LPC */
+	pci_write_config16(PCH_DEV_LPC, LPC_IO_DECODE, com_ranges);
+	/* Enable ComA and ComB Port */
+	lpc_enable_fixed_io_ranges(com_enable);
+}
+
+static int apl_lpc_probe(struct udevice *dev)
+{
+	if (spl_phase() == PHASE_TPL)
+		lpc_configure_pads();
+
+	return 0;
+}
+
+static const struct udevice_id apl_lpc_ids[] = {
+	{ .compatible = "intel,apl-lpc" },
+	{ }
+};
+
+U_BOOT_DRIVER(apl_lpc_drv) = {
+	.name		= "intel_apl_lpc",
+	.id		= UCLASS_LPC,
+	.of_match	= apl_lpc_ids,
+	.probe		= apl_lpc_probe,
+};
diff --git a/arch/x86/include/asm/arch-apollolake/lpc.h b/arch/x86/include/asm/arch-apollolake/lpc.h
new file mode 100644
index 00000000000..641ccc01ca5
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/lpc.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Take from coreboot project file of the same name
+ */
+
+#ifndef __ARCH_LPC_H
+#define __ARCH_LPC_H
+
+#define LPC_SERIRQ_CTL			0x64
+#define  LPC_SCNT_EN			(1 << 7)
+#define  LPC_SCNT_MODE			(1 << 6)
+#define LPC_IO_DECODE			0x80
+#define  LPC_IOD_COMA_RANGE             (0 << 0) /* 0x3F8 - 0x3FF COMA*/
+#define  LPC_IOD_COMB_RANGE             (1 << 4) /* 0x2F8 - 0x2FF COMB*/
+/*
+ * Use IO_<peripheral>_<IO port> style macros defined in lpc_lib.h
+ * to enable decoding of I/O locations for a peripheral
+ */
+#define LPC_IO_ENABLES			0x82
+#define LPC_GENERIC_IO_RANGE(n)		((((n) & 0x3) * 4) + 0x84)
+#define  LPC_LGIR_AMASK_MASK		(0xfc << 16)
+#define  LPC_LGIR_ADDR_MASK		0xfffc
+#define  LPC_LGIR_EN			(1 << 0)
+#define LPC_LGIR_MAX_WINDOW_SIZE	256
+#define LPC_GENERIC_MEM_RANGE		0x98
+#define  LPC_LGMR_ADDR_MASK		0xffff0000
+#define  LPC_LGMR_EN			(1 << 0)
+#define LPC_LGMR_WINDOW_SIZE		(64 * KiB)
+#define LPC_BIOS_CNTL			0xdc
+#define  LPC_BC_BILD			(1 << 7) /* BILD */
+#define  LPC_BC_LE			(1 << 1) /* LE */
+#define  LPC_BC_EISS			(1 << 5) /* EISS */
+#define LPC_PCCTL			0xE0 /* PCI Clock Control */
+#define  LPC_PCCTL_CLKRUN_EN		(1 << 0)
+
+/*
+ * IO decode enable macros are in the format IO_<peripheral>_<IO port>.
+ * For example, to open ports 0x60, 0x64 for the keyboard controller,
+ * use IOE_KBC_60_64 macro. For IOE_ macros that do not specify a port range,
+ * the port range is selectable via the IO decodes register.
+ */
+#define LPC_IOE_EC_4E_4F               BIT(13)
+#define LPC_IOE_SUPERIO_2E_2F          BIT(12)
+#define LPC_IOE_EC_62_66               BIT(11)
+#define LPC_IOE_KBC_60_64              BIT(10)
+#define LPC_IOE_HGE_208                BIT(9)
+#define LPC_IOE_LGE_200                BIT(8)
+#define LPC_IOE_FDD_EN                 BIT(3)
+#define LPC_IOE_LPT_EN                 BIT(2)
+#define LPC_IOE_COMB_EN                BIT(1)
+#define LPC_IOE_COMA_EN                BIT(0)
+#define LPC_NUM_GENERIC_IO_RANGES       4
+
+#define LPC_IO_ENABLES			0x82
+
+void lpc_enable_fixed_io_ranges(uint io_enables);
+int lpc_open_pmio_window(uint base, uint size);
+void lpc_io_setup_comm_a_b(void);
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 099/108] x86: apollolake: Add PCH driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (75 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 098/108] x86: apollolake: Add LPC driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 100/108] x86: apollolake: Add PUNIT driver Simon Glass
                   ` (10 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add a driver for the apollolake Platform Controller Hub. It does not have
any functionality and is just a placeholder for now.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2:
- Drop probe() function
- Implement set_spi_protect()

 arch/x86/cpu/apollolake/Makefile           |  1 +
 arch/x86/cpu/apollolake/pch.c              | 36 ++++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/pch.h |  9 ++++++
 3 files changed, 46 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/pch.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/pch.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 71c3cd08241..7f76572e551 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -9,5 +9,6 @@ obj-y += hostbridge.o
 obj-y += itss.o
 obj-y += lpc.o
 obj-y += lpss.o
+obj-y += pch.o
 obj-y += pmc.o
 obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/pch.c b/arch/x86/cpu/apollolake/pch.c
new file mode 100644
index 00000000000..89667b65224
--- /dev/null
+++ b/arch/x86/cpu/apollolake/pch.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pch.h>
+#include <spl.h>
+#include <asm/lpc_common.h>
+
+#define BIOS_CTRL	0xdc
+
+static int apl_set_spi_protect(struct udevice *dev, bool protect)
+{
+	if (spl_phase() != PHASE_TPL)
+		return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
+
+	return 0;
+}
+
+static const struct pch_ops apl_pch_ops = {
+	.set_spi_protect = apl_set_spi_protect,
+};
+
+static const struct udevice_id apl_pch_ids[] = {
+	{ .compatible = "intel,apl-pch" },
+	{ }
+};
+
+U_BOOT_DRIVER(apl_pch) = {
+	.name		= "apl_pch",
+	.id		= UCLASS_PCH,
+	.of_match	= apl_pch_ids,
+	.ops		= &apl_pch_ops,
+};
diff --git a/arch/x86/include/asm/arch-apollolake/pch.h b/arch/x86/include/asm/arch-apollolake/pch.h
new file mode 100644
index 00000000000..7f19903a3fe
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/pch.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ASM_ARCH_PCH_H
+#define __ASM_ARCH_PCH_H
+
+#endif /* __ASM_ARCH_PCH_H */
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 100/108] x86: apollolake: Add PUNIT driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (76 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 099/108] x86: apollolake: Add PCH driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  8:47   ` Andy Shevchenko
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 101/108] x86: apollolake: Add SPL loaders Simon Glass
                   ` (9 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add a driver for the apollolake power unit. It is modelled as a syscon
driver since it only needs to be probed.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use pci_get_devfn()

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile |   3 +
 arch/x86/cpu/apollolake/punit.c  | 121 +++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/punit.c

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 7f76572e551..8a177d93d00 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -3,6 +3,9 @@
 # Copyright (c) 2016 Google, Inc
 
 obj-$(CONFIG_SPL_BUILD) += systemagent.o
+ifndef CONFIG_TPL_BUILD
+obj-y += punit.o
+endif
 
 obj-y += gpio.o
 obj-y += hostbridge.o
diff --git a/arch/x86/cpu/apollolake/punit.c b/arch/x86/cpu/apollolake/punit.c
new file mode 100644
index 00000000000..c8e55a24d8a
--- /dev/null
+++ b/arch/x86/cpu/apollolake/punit.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/systemagent.h>
+
+/**
+ * struct apl_punit_platdata - platform data for punit
+ *
+ * @pciex_region_size: BAR length in bytes
+ */
+struct apl_punit_platdata {
+	pci_dev_t bdf;
+};
+
+/*
+ * Punit Initialization code. This all isn't documented, but
+ * this is the recipe.
+ */
+static int punit_init(struct udevice *dev)
+{
+	struct apl_punit_platdata *plat = dev_get_platdata(dev);
+	struct udevice *cpu;
+	u32 reg;
+	ulong start;
+	int ret;
+
+	/* Thermal throttle activation offset */
+	ret = uclass_first_device_err(UCLASS_CPU, &cpu);
+	if (ret)
+		return log_msg_ret("Cannot find CPU", ret);
+	cpu_configure_thermal_target(cpu);
+
+	/*
+	 * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
+	 * Enable all cores here.
+	 */
+	writel(0, MCHBAR_REG(CORE_DISABLE_MASK));
+
+	/* P-Unit bring up */
+	reg = readl(MCHBAR_REG(BIOS_RESET_CPL));
+	if (reg == 0xffffffff) {
+		/* P-unit not found */
+		debug("Punit MMIO not available\n");
+		return -ENOENT;
+	}
+
+	/* Set Punit interrupt pin IPIN offset 3D */
+	pci_x86_write_config(plat->bdf, PCI_INTERRUPT_PIN, 0x2, PCI_SIZE_8);
+
+	/* Set PUINT IRQ to 24 and INTPIN LOCK */
+	writel(PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
+	       PUINT_THERMAL_DEVICE_IRQ_LOCK,
+	       MCHBAR_REG(PUNIT_THERMAL_DEVICE_IRQ));
+
+	if (!IS_ENABLED(SOC_INTEL_GLK))
+		clrsetbits_le32(MCHBAR_REG(0x7818), 0x1fe0, 0x220);
+
+	/* Stage0 BIOS Reset Complete (RST_CPL) */
+	enable_bios_reset_cpl();
+
+	/*
+	 * Poll for bit 8 to check if PCODE has completed its action in response
+	 * to BIOS Reset complete.  We wait here till 1 ms for the bit to get
+	 * set.
+	 */
+	start = get_timer(0);
+	while (!(readl(MCHBAR_REG(BIOS_RESET_CPL)) & PCODE_INIT_DONE)) {
+		if (get_timer(start) > 1) {
+			debug("PCODE Init Done timeout\n");
+			return -ETIMEDOUT;
+		}
+		udelay(100);
+	}
+	debug("PUNIT init complete\n");
+
+	return 0;
+}
+
+static int apl_punit_probe(struct udevice *dev)
+{
+	if (spl_phase() == PHASE_SPL)
+		return punit_init(dev);
+
+	return 0;
+}
+
+static int apl_punit_ofdata_to_platdata(struct udevice *dev)
+{
+	struct apl_punit_platdata *plat = dev_get_platdata(dev);
+	int root;
+
+	root = pci_get_devfn(dev);
+	if (root < 0)
+		return log_msg_ret("Cannot get host-bridge PCI address", root);
+	plat->bdf = root;
+
+	return 0;
+}
+
+static const struct udevice_id apl_syscon_ids[] = {
+	{ .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_intel_punit) = {
+	.name		= "intel_punit_syscon",
+	.id		= UCLASS_SYSCON,
+	.of_match	= apl_syscon_ids,
+	.ofdata_to_platdata = apl_punit_ofdata_to_platdata,
+	.probe		= apl_punit_probe,
+};
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 101/108] x86: apollolake: Add SPL loaders
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (77 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 100/108] x86: apollolake: Add PUNIT driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 102/108] x86: apollolake: Add a CPU driver Simon Glass
                   ` (8 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add loaders for SPL and TPL so that the next stage can be loaded from
memory-mapped SPI or, failing that, the Fast SPI driver.

Signed-off-by: Simon Glass <sjg@chromium.org>

---

Changes in v3:
- Add a driver for APL SPI for TPL (using of-platdata)
- Support TPL without CONFIG_TPL_SPI_SUPPORT
- Support bootstage timing

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile |   2 +
 arch/x86/cpu/apollolake/spl.c    | 202 +++++++++++++++++++++++++++++++
 2 files changed, 204 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/spl.c

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 8a177d93d00..c4ec71e2b76 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -2,7 +2,9 @@
 #
 # Copyright (c) 2016 Google, Inc
 
+obj-$(CONFIG_SPL_BUILD) += spl.o
 obj-$(CONFIG_SPL_BUILD) += systemagent.o
+
 ifndef CONFIG_TPL_BUILD
 obj-y += punit.o
 endif
diff --git a/arch/x86/cpu/apollolake/spl.c b/arch/x86/cpu/apollolake/spl.c
new file mode 100644
index 00000000000..a12379e312d
--- /dev/null
+++ b/arch/x86/cpu/apollolake/spl.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <binman_sym.h>
+#include <dm.h>
+#include <spi.h>
+#include <spl.h>
+#include <spi_flash.h>
+#include <asm/fast_spi.h>
+#include <asm/spl.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/iomap.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/*
+ * We need to read well past the end of the region in order for execution from
+ * the loaded data to work. It is not clear why.
+ */
+#define SAFETY_MARGIN	0x4000
+
+binman_sym_declare(ulong, u_boot_spl, image_pos);
+binman_sym_declare(ulong, u_boot_spl, size);
+/* U-Boot image_pos is declared by common/spl/spl.c */
+binman_sym_declare(ulong, u_boot_any, size);
+
+static ulong get_image_pos(void)
+{
+	return spl_phase() == PHASE_TPL ?
+		binman_sym(ulong, u_boot_spl, image_pos) :
+		binman_sym(ulong, u_boot_any, image_pos);
+}
+
+static ulong get_image_size(void)
+{
+	return spl_phase() == PHASE_TPL ?
+		binman_sym(ulong, u_boot_spl, size) :
+		binman_sym(ulong, u_boot_any, size);
+}
+
+/* This reads the next phase from mapped SPI flash */
+static int rom_load_image(struct spl_image_info *spl_image,
+			  struct spl_boot_device *bootdev)
+{
+	ulong spl_pos = get_image_pos();
+	ulong spl_size = get_image_size();
+	struct udevice *dev;
+	ulong map_base;
+	size_t map_size;
+	uint offset;
+	int ret;
+
+	spl_image->size = CONFIG_SYS_MONITOR_LEN;  /* We don't know SPL size */
+	spl_image->entry_point = spl_phase() == PHASE_TPL ?
+		CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
+	spl_image->load_addr = spl_image->entry_point;
+	spl_image->os = IH_OS_U_BOOT;
+	spl_image->name = "U-Boot";
+	debug("Reading from mapped SPI %lx, size %lx", spl_pos, spl_size);
+
+	if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
+		ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
+		if (ret)
+			return log_msg_ret("spi_flash", ret);
+		if (!dev)
+			return log_msg_ret("spi_flash dev", -ENODEV);
+		ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
+		if (ret)
+			return log_msg_ret("mmap", ret);
+	} else {
+		ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
+					     &offset);
+		if (ret)
+			return ret;
+	}
+	spl_pos += map_base & ~0xff000000;
+	debug(", base %lx, pos %lx\n", map_base, spl_pos);
+	bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
+	memcpy((void *)spl_image->load_addr, (void *)spl_pos,
+	       spl_size + SAFETY_MARGIN);
+	bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
+
+	return 0;
+}
+SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image);
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)
+
+static int apl_flash_std_read(struct udevice *dev, u32 offset, size_t len,
+			      void *buf)
+{
+	struct spi_flash *flash = dev_get_uclass_priv(dev);
+	struct mtd_info *mtd = &flash->mtd;
+	size_t retlen;
+
+	return log_ret(mtd->_read(mtd, offset, len, &retlen, buf));
+}
+
+static int apl_flash_probe(struct udevice *dev)
+{
+	return spi_flash_std_probe(dev);
+}
+
+/*
+ * Manually set the parent of the SPI flash to SPI, since dtoc doesn't. We also
+ * need to allocate the parent_platdata since by the time this function is
+ * called device_bind() has already gone past that step.
+ */
+static int apl_flash_bind(struct udevice *dev)
+{
+	if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+		struct dm_spi_slave_platdata *plat;
+		struct udevice *spi;
+		int ret;
+
+		ret = uclass_first_device_err(UCLASS_SPI, &spi);
+		if (ret)
+			return ret;
+		dev->parent = spi;
+
+		plat = calloc(sizeof(*plat), 1);
+		if (!plat)
+			return -ENOMEM;
+		dev->parent_platdata = plat;
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_flash_ops apl_flash_ops = {
+	.read		= apl_flash_std_read,
+};
+
+static const struct udevice_id apl_flash_ids[] = {
+	{ .compatible = "jedec,spi-nor" },
+	{ }
+};
+
+U_BOOT_DRIVER(winbond_w25q128fw) = {
+	.name		= "winbond_w25q128fw",
+	.id		= UCLASS_SPI_FLASH,
+	.of_match	= apl_flash_ids,
+	.bind		= apl_flash_bind,
+	.probe		= apl_flash_probe,
+	.priv_auto_alloc_size = sizeof(struct spi_flash),
+	.ops		= &apl_flash_ops,
+};
+
+/* This uses a SPI flash device to read the next phase */
+static int spl_fast_spi_load_image(struct spl_image_info *spl_image,
+				   struct spl_boot_device *bootdev)
+{
+	ulong spl_pos = get_image_pos();
+	ulong spl_size = get_image_size();
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
+	if (ret)
+		return ret;
+
+	spl_image->size = CONFIG_SYS_MONITOR_LEN;  /* We don't know SPL size */
+	spl_image->entry_point = spl_phase() == PHASE_TPL ?
+		CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
+	spl_image->load_addr = spl_image->entry_point;
+	spl_image->os = IH_OS_U_BOOT;
+	spl_image->name = "U-Boot";
+	spl_pos &= ~0xff000000;
+	debug("Reading from flash %lx, size %lx\n", spl_pos, spl_size);
+	ret = spi_flash_read_dm(dev, spl_pos, spl_size + SAFETY_MARGIN,
+				(void *)spl_image->load_addr);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+SPL_LOAD_IMAGE_METHOD("Fast SPI", 1, BOOT_DEVICE_FAST_SPI,
+		      spl_fast_spi_load_image);
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	bool use_spi_flash = BOOT_FROM_FAST_SPI_FLASH;
+
+	if (use_spi_flash) {
+		spl_boot_list[0] = BOOT_DEVICE_FAST_SPI;
+		spl_boot_list[1] = BOOT_DEVICE_SPI_MMAP;
+	} else {
+		spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
+		spl_boot_list[1] = BOOT_DEVICE_FAST_SPI;
+	}
+}
+
+#else
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
+}
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 102/108] x86: apollolake: Add a CPU driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (78 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 101/108] x86: apollolake: Add SPL loaders Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 103/108] x86: apollolake: Add SPL/TPL init Simon Glass
                   ` (7 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add a bare-bones CPU driver so that CPUs can be probed.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add two more defines for the CPU driver
- Expand comments for BOOT_FROM_FAST_SPI_FLASH

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile           |  1 +
 arch/x86/cpu/apollolake/cpu.c              | 51 ++++++++++++++++++++++
 arch/x86/include/asm/arch-apollolake/cpu.h | 27 ++++++++++++
 3 files changed, 79 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/cpu.c
 create mode 100644 arch/x86/include/asm/arch-apollolake/cpu.h

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index c4ec71e2b76..ee7114b40c9 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_SPL_BUILD) += spl.o
 obj-$(CONFIG_SPL_BUILD) += systemagent.o
 
 ifndef CONFIG_TPL_BUILD
+obj-y += cpu.o
 obj-y += punit.o
 endif
 
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c
new file mode 100644
index 00000000000..f248623eb49
--- /dev/null
+++ b/arch/x86/cpu/apollolake/cpu.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <asm/cpu_common.h>
+#include <asm/cpu_x86.h>
+
+struct cpu_apollolake_priv {
+};
+
+static int apollolake_get_info(struct udevice *dev, struct cpu_info *info)
+{
+	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+}
+
+static int apollolake_get_count(struct udevice *dev)
+{
+	return 4;
+}
+
+static int cpu_x86_apollolake_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct cpu_ops cpu_x86_apollolake_ops = {
+	.get_desc	= cpu_x86_get_desc,
+	.get_info	= apollolake_get_info,
+	.get_count	= apollolake_get_count,
+	.get_vendor	= cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_apollolake_ids[] = {
+	{ .compatible = "intel,apl-cpu" },
+	{ }
+};
+
+U_BOOT_DRIVER(cpu_x86_apollolake_drv) = {
+	.name		= "cpu_x86_apollolake",
+	.id		= UCLASS_CPU,
+	.of_match	= cpu_x86_apollolake_ids,
+	.bind		= cpu_x86_bind,
+	.probe		= cpu_x86_apollolake_probe,
+	.ops		= &cpu_x86_apollolake_ops,
+	.priv_auto_alloc_size	= sizeof(struct cpu_apollolake_priv),
+	.flags		= DM_FLAG_PRE_RELOC,
+};
diff --git a/arch/x86/include/asm/arch-apollolake/cpu.h b/arch/x86/include/asm/arch-apollolake/cpu.h
new file mode 100644
index 00000000000..3047d502fab
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/cpu.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ASM_ARCH_CPU_H
+#define __ASM_ARCH_CPU_H
+
+/* Common Timer Copy (CTC) frequency - 19.2MHz */
+#define CTC_FREQ		19200000
+
+/*
+ * Set to true to use the fast SPI driver to boot, instead of mapped SPI.
+ * You also need to enabled CONFIG_SUPPORT_SPI_FLASHBOOT.
+ */
+#define BOOT_FROM_FAST_SPI_FLASH	false
+
+/*
+ * We need to read well past the end of the region in order for execution from
+ * the loaded data to work. It is not clear why.
+ */
+#define SAFETY_MARGIN	0x4000
+
+#define MAX_PCIE_PORTS		6
+#define CLKREQ_DISABLED		0xf
+
+#endif /* __ASM_ARCH_CPU_H */
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 103/108] x86: apollolake: Add SPL/TPL init
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (79 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 102/108] x86: apollolake: Add a CPU driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver Simon Glass
                   ` (6 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add code to init the system both in TPL and SPL. Each phase has its own
procedure.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Adjust fast_spi_cache_bios_region() to avoid using SPI driver
- Drop calls to x86_cpu_init_f(), x86_cpu_reinit_f()
- Fix build error when debug UART is disabled
- Init the p2sb before the northbridge since the latter so it can use GPIOs
- Move location of fast_spi.h header file
- Shorten log_msg_ret() calls since the function name is always printed
- Support TPL without CONFIG_TPL_SPI_SUPPORT (reduces code size)

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile  |   1 +
 arch/x86/cpu/apollolake/cpu_spl.c | 278 ++++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/cpu_spl.c

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index ee7114b40c9..65c17d4b779 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -2,6 +2,7 @@
 #
 # Copyright (c) 2016 Google, Inc
 
+obj-$(CONFIG_SPL_BUILD) += cpu_spl.o
 obj-$(CONFIG_SPL_BUILD) += spl.o
 obj-$(CONFIG_SPL_BUILD) += systemagent.o
 
diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c
new file mode 100644
index 00000000000..fc9b5eb4f64
--- /dev/null
+++ b/arch/x86/cpu/apollolake/cpu_spl.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Portions taken from coreboot
+ */
+
+#include <common.h>
+#include <acpi_s3.h>
+#include <dm.h>
+#include <ec_commands.h>
+#include <log.h>
+#include <spi_flash.h>
+#include <spl.h>
+#include <syscon.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/cpu_x86.h>
+#include <asm/fast_spi.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/gpio_apl.h>
+#include <asm/arch/gpio_defs.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/lpc.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/systemagent.h>
+#include <asm/arch/uart.h>
+#include <asm/fsp2/fsp_api.h>
+#include <power/acpi_pmc.h>
+
+/* Define this here to avoid referencing any drivers for the debug UART 1 */
+#define PCH_DEV_P2SB	PCI_BDF(0, 0x0d, 0)
+
+static void pch_uart_init(void)
+{
+	/*
+	 * Set up the pinmux so that the UART rx/tx signals are connected
+	 * outside the SoC.
+	 *
+	 * There are about 500 lines of code required to program the GPIO
+	 * configuration for the UARTs. But it boils down to four writes, and
+	 * for the debug UART we want the minimum possible amount of code before
+	 * the UART is running. So just add the magic writes here. See
+	 * apl_gpio_early_init() for the full horror.
+	 */
+	if (PCI_FUNC(PCH_DEV_UART) == 1) {
+		writel(0x40000402, 0xd0c50650);
+		writel(0x3c47, 0xd0c50654);
+		writel(0x40000400, 0xd0c50658);
+		writel(0x3c48, 0xd0c5065c);
+	} else { /* UART2 */
+		writel(0x40000402, 0xd0c50670);
+		writel(0x3c4b, 0xd0c50674);
+		writel(0x40000400, 0xd0c50678);
+		writel(0x3c4c, 0xd0c5067c);
+	}
+
+#ifdef CONFIG_DEBUG_UART
+	apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
+#endif
+}
+
+static void p2sb_enable_bar(ulong bar)
+{
+	/* Enable PCR Base address in PCH */
+	pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
+			     PCI_SIZE_32);
+	pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+	/* Enable P2SB MSE */
+	pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
+			     PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
+			     PCI_SIZE_8);
+}
+
+/*
+ * init_for_uart() - Init the debug UART ready for use
+ *
+ * This is the minimum init needed to get the UART running. It avoids any
+ * drivers or complex code, so that the UART is running as soon as possible.
+ */
+static void init_for_uart(void)
+{
+	p2sb_enable_bar(IOMAP_P2SB_BAR);
+	pch_uart_init();
+}
+
+static int fast_spi_cache_bios_region(void)
+{
+	uint map_size, offset;
+	ulong map_base, base;
+	int ret;
+
+	ret = fast_spi_early_init(PCH_DEV_SPI, IOMAP_SPI_BASE);
+	if (ret)
+		return log_msg_ret("early_init", ret);
+
+	ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
+				     &offset);
+	if (ret)
+		return log_msg_ret("get_mmap", ret);
+
+	base = (4ULL << 30) - map_size;
+	mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
+	log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
+
+	return 0;
+}
+
+static void enable_pm_timer_emulation(struct udevice *pmc)
+{
+	struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
+	msr_t msr;
+
+	/*
+	 * The derived frequency is calculated as follows:
+	 *    (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
+	 *
+	 * Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
+	 * used.
+	 */
+	msr.hi = (3579545ULL << 32) / CTC_FREQ;
+
+	/* Set PM1 timer IO port and enable */
+	msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
+	debug("PM timer %x %x\n", msr.hi, msr.lo);
+	msr_write(MSR_EMULATE_PM_TIMER, msr);
+}
+
+static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
+{
+	uint base;
+	uint size;
+
+	if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) {
+		base = MEC_EMI_BASE;
+		size = MEC_EMI_SIZE;
+	} else {
+		base = EC_HOST_CMD_REGION0;
+		size = 2 * EC_HOST_CMD_REGION_SIZE;
+		/* Make sure MEMMAP region follows host cmd region */
+		assert(base + size == EC_LPC_ADDR_MEMMAP);
+		size += EC_MEMMAP_SIZE;
+	}
+
+	*out_basep = base;
+	*out_sizep = size;
+}
+
+static void early_ec_init(void)
+{
+	uint base, size;
+
+	/*
+	 * Set up LPC decoding for the Chrome OS EC I/O port ranges:
+	 * - Ports 62/66, 60/64, and 200->208
+	 * - Chrome OS EC communication I/O ports
+	 */
+	lpc_enable_fixed_io_ranges(LPC_IOE_EC_62_66 | LPC_IOE_KBC_60_64 |
+				   LPC_IOE_LGE_200);
+	google_chromeec_ioport_range(&base, &size);
+	lpc_open_pmio_window(base, size);
+}
+
+static int arch_cpu_init_tpl(void)
+{
+	struct udevice *pmc, *sa, *p2sb, *gpio, *serial, *spi, *lpc;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
+	if (ret)
+		return log_msg_ret("PMC", ret);
+
+	/* Clear global reset promotion bit */
+	ret = pmc_global_reset_set_enable(pmc, false);
+	if (ret)
+		return log_msg_ret("disable global reset", ret);
+
+	enable_pm_timer_emulation(pmc);
+
+	ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
+	if (ret)
+		return log_msg_ret("p2sb", ret);
+	ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa);
+	if (ret)
+		return log_msg_ret("northbridge", ret);
+	ret = uclass_first_device_err(UCLASS_GPIO, &gpio);
+	if (ret)
+		return log_msg_ret("gpio", ret);
+	gd->baudrate = CONFIG_BAUDRATE;
+	ret = uclass_first_device_err(UCLASS_SERIAL, &serial);
+	if (ret)
+		return log_msg_ret("serial", ret);
+	if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
+		ret = uclass_first_device_err(UCLASS_SPI, &spi);
+		if (ret)
+			return log_msg_ret("SPI", ret);
+	} else {
+		/* Alternative code if we don't have SPI in TPL */
+		if (BOOT_FROM_FAST_SPI_FLASH)
+			printf("Warning: Enable APL_SPI_FLASHBOOT to use SPI-flash driver in TPL");
+		ret = fast_spi_cache_bios_region();
+		if (ret)
+			return log_msg_ret("BIOS cache", ret);
+	}
+	ret = pmc_disable_tco(pmc);
+	if (ret)
+		return log_msg_ret("disable TCO", ret);
+	ret = pmc_gpe_init(gpio);
+	if (ret)
+		return log_msg_ret("pmc_gpe", ret);
+	ret = uclass_first_device_err(UCLASS_LPC, &lpc);
+	if (ret)
+		return log_msg_ret("lpc", ret);
+
+	early_ec_init();
+
+	return 0;
+}
+
+/*
+ * Enables several BARs and devices which are needed for memory init
+ * - MCH_BASE_ADDR is needed in order to talk to the memory controller
+ * - HPET is enabled because FSP wants to store a pointer to global data in the
+ *   HPET comparator register
+ */
+static int arch_cpu_init_spl(void)
+{
+	struct udevice *pmc, *p2sb;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
+	if (ret)
+		return log_msg_ret("Could not probe PMC", ret);
+	ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
+	if (ret)
+		return log_msg_ret("Cannot set up p2sb", ret);
+
+	lpc_io_setup_comm_a_b();
+	/* enable_rtc_upper_bank(); */
+
+	ret = pmc_init(pmc);
+	if (ret < 0)
+		return log_msg_ret("Could not init PMC", ret);
+#ifdef CONFIG_HAVE_ACPI_RESUME
+	ret = pmc_prev_sleep_state(pmc);
+	if (ret < 0)
+		return log_msg_ret("Could not get PMC sleep state", ret);
+	gd->arch.prev_sleep_state = ret;
+#endif
+
+	return 0;
+}
+
+int arch_cpu_init(void)
+{
+	int ret = 0;
+
+	if (spl_phase() == PHASE_TPL)
+		ret = arch_cpu_init_tpl();
+	else if (spl_phase() == PHASE_SPL)
+		ret = arch_cpu_init_spl();
+	if (ret)
+		printf("%s: Error %d\n", __func__, ret);
+
+	return ret;
+}
+
+void board_debug_uart_init(void)
+{
+	init_for_uart();
+}
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (80 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 103/108] x86: apollolake: Add SPL/TPL init Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  8:49   ` Andy Shevchenko
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 105/108] x86: apollolake: Add Kconfig and Makefile Simon Glass
                   ` (5 subsequent siblings)
  87 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Adds a driver for the apollolake Primary-to-sideband bus. This supports
various child devices. It supposed both device tree and of-platdata.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use pci_get_devfn()

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile |   1 +
 arch/x86/cpu/apollolake/p2sb.c   | 167 +++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/p2sb.c

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 65c17d4b779..7b040c37a72 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -16,6 +16,7 @@ obj-y += hostbridge.o
 obj-y += itss.o
 obj-y += lpc.o
 obj-y += lpss.o
+obj-y += p2sb.o
 obj-y += pch.o
 obj-y += pmc.o
 obj-y += uart.o
diff --git a/arch/x86/cpu/apollolake/p2sb.c b/arch/x86/cpu/apollolake/p2sb.c
new file mode 100644
index 00000000000..b5244ace775
--- /dev/null
+++ b/arch/x86/cpu/apollolake/p2sb.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Primary-to-Sideband Bridge
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_P2SB
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <p2sb.h>
+#include <spl.h>
+#include <asm/pci.h>
+
+struct p2sb_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_intel_apl_p2sb dtplat;
+#endif
+	ulong mmio_base;
+	pci_dev_t bdf;
+};
+
+/* PCI config space registers */
+#define HPTC_OFFSET		0x60
+#define HPTC_ADDR_ENABLE_BIT	(1 << 7)
+
+/* High Performance Event Timer Configuration */
+#define P2SB_HPTC				0x60
+#define P2SB_HPTC_ADDRESS_ENABLE		(1 << 7)
+
+/*
+ * ADDRESS_SELECT            ENCODING_RANGE
+ *      0                 0xfed0 0000 - 0xfed0 03ff
+ *      1                 0xfed0 1000 - 0xfed0 13ff
+ *      2                 0xfed0 2000 - 0xfed0 23ff
+ *      3                 0xfed0 3000 - 0xfed0 33ff
+ */
+#define P2SB_HPTC_ADDRESS_SELECT_0		(0 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_1		(1 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_2		(2 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_3		(3 << 0)
+
+/*
+ * apl_p2sb_early_init() - Enable decoding for HPET range
+ *
+ * This is needed for FspMemoryInit to store and retrieve a global data
+ * pointer
+ *
+ * @dev: P2SB device
+ * @return 0 if OK, -ve on error
+ */
+static int apl_p2sb_early_init(struct udevice *dev)
+{
+	struct p2sb_platdata *plat = dev_get_platdata(dev);
+	pci_dev_t pdev = plat->bdf;
+
+	/*
+	 * Enable decoding for HPET memory address range.
+	 * HPTC_OFFSET(0x60) bit 7, when set the P2SB will decode
+	 * the High Performance Timer memory address range
+	 * selected by bits 1:0
+	 */
+	pci_x86_write_config(pdev, HPTC_OFFSET, HPTC_ADDR_ENABLE_BIT,
+			     PCI_SIZE_8);
+
+	/* Enable PCR Base address in PCH */
+	pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0, plat->mmio_base,
+			     PCI_SIZE_32);
+	pci_x86_write_config(pdev, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+	/* Enable P2SB MSE */
+	pci_x86_write_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
+			     PCI_COMMAND_MEMORY, PCI_SIZE_8);
+
+	return 0;
+}
+
+static int apl_p2sb_spl_init(struct udevice *dev)
+{
+	/* Enable decoding for HPET. Needed for FSP global pointer storage */
+	dm_pci_write_config(dev, P2SB_HPTC, P2SB_HPTC_ADDRESS_SELECT_0 |
+			    P2SB_HPTC_ADDRESS_ENABLE, PCI_SIZE_8);
+
+	return 0;
+}
+
+int apl_p2sb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev);
+	struct p2sb_platdata *plat = dev_get_platdata(dev);
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	int ret;
+
+	if (spl_phase() == PHASE_TPL) {
+		u32 base[2];
+
+		/* TPL sets up the initial BAR */
+		ret = dev_read_u32_array(dev, "early-regs", base,
+					 ARRAY_SIZE(base));
+		if (ret)
+			return log_msg_ret("Missing/short early-regs", ret);
+		plat->mmio_base = base[0];
+		plat->bdf = pci_get_devfn(dev);
+		if (plat->bdf < 0)
+			return log_msg_ret("Cannot get p2sb PCI address",
+					   plat->bdf);
+	} else {
+		plat->mmio_base = dev_read_addr_pci(dev);
+		/* Don't set BDF since it should not be used */
+		if (plat->mmio_base == FDT_ADDR_T_NONE)
+			return -EINVAL;
+	}
+#else
+	plat->mmio_base = plat->dtplat.early_regs[0];
+	plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
+#endif
+	upriv->mmio_base = plat->mmio_base;
+	debug("p2sb: mmio_base=%x\n", (uint)plat->mmio_base);
+
+	return 0;
+}
+
+static int apl_p2sb_probe(struct udevice *dev)
+{
+	if (spl_phase() == PHASE_TPL)
+		return apl_p2sb_early_init(dev);
+	else if (spl_phase() == PHASE_SPL)
+		return apl_p2sb_spl_init(dev);
+
+	return 0;
+}
+
+static int p2sb_child_post_bind(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
+	int ret;
+	u32 pid;
+
+	ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
+	if (ret)
+		return ret;
+	pplat->pid = pid;
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id apl_p2sb_ids[] = {
+	{ .compatible = "intel,apl-p2sb" },
+	{ }
+};
+
+U_BOOT_DRIVER(apl_p2sb_drv) = {
+	.name		= "intel_apl_p2sb",
+	.id		= UCLASS_P2SB,
+	.of_match	= apl_p2sb_ids,
+	.probe		= apl_p2sb_probe,
+	.ofdata_to_platdata = apl_p2sb_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct p2sb_platdata),
+	.per_child_platdata_auto_alloc_size =
+		sizeof(struct p2sb_child_platdata),
+	.child_post_bind = p2sb_child_post_bind,
+};
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 105/108] x86: apollolake: Add Kconfig and Makefile
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (81 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 106/108] x86: apollolake: Add FSP structures Simon Glass
                   ` (4 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add basic plumbing to allow apollolake support to be used.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add MMC, video, USB configs
- Add an APL_SPI_FLASH_BOOT option to enable non-mmap boot
- Fix the incorrect value of CPU_ADDR_BITS

Changes in v2: None

 arch/x86/Kconfig                |  1 +
 arch/x86/cpu/Makefile           |  1 +
 arch/x86/cpu/apollolake/Kconfig | 87 +++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/Kconfig

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c9f1b6d8ada..36a0021adb7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -106,6 +106,7 @@ source "board/google/Kconfig"
 source "board/intel/Kconfig"
 
 # platform-specific options below
+source "arch/x86/cpu/apollolake/Kconfig"
 source "arch/x86/cpu/baytrail/Kconfig"
 source "arch/x86/cpu/braswell/Kconfig"
 source "arch/x86/cpu/broadwell/Kconfig"
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index b6a010ea320..4c151f8c94d 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -41,6 +41,7 @@ extra-y += call32.o
 endif
 
 obj-y += intel_common/
+obj-$(CONFIG_INTEL_APOLLOLAKE) += apollolake/
 obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
 obj-$(CONFIG_INTEL_BRASWELL) += braswell/
 obj-$(CONFIG_INTEL_BROADWELL) += broadwell/
diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig
new file mode 100644
index 00000000000..e49ba5cb512
--- /dev/null
+++ b/arch/x86/cpu/apollolake/Kconfig
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC
+#
+
+config INTEL_APOLLOLAKE
+	bool
+	select FSP_VERSION2
+	select HAVE_FSP
+	select ARCH_MISC_INIT
+	select USE_CAR
+	select INTEL_PMC
+	select TPL_X86_TSC_TIMER_NATIVE
+	select SPL_PCH_SUPPORT
+	select TPL_PCH_SUPPORT
+	select PCH_SUPPORT
+	select P2SB
+	imply ENABLE_MRC_CACHE
+	imply AHCI_PCI
+	imply SCSI
+	imply SCSI_AHCI
+	imply SPI_FLASH
+	imply USB
+	imply USB_EHCI_HCD
+	imply TPL
+	imply SPL
+	imply TPL_X86_16BIT_INIT
+	imply TPL_OF_PLATDATA
+	imply ACPI_PMC
+	imply MMC
+	imply DM_MMC
+	imply MMC_PCI
+	imply MMC_SDHCI
+	imply CMD_MMC
+	imply VIDEO_FSP
+
+if INTEL_APOLLOLAKE
+
+config DCACHE_RAM_BASE
+	default 0xfef00000
+
+config DCACHE_RAM_SIZE
+	default 0xc0000
+
+config DCACHE_RAM_MRC_VAR_SIZE
+	default 0xb0000
+
+config CPU_SPECIFIC_OPTIONS
+	def_bool y
+	select SMM_TSEG
+	select X86_RAMTEST
+
+config SMM_TSEG_SIZE
+	hex
+	default 0x800000
+
+config MMCONF_BASE_ADDRESS
+	hex
+	default 0xe0000000
+
+config INTEL_GPIO_DUAL_ROUTE_SUPPORT
+	def_bool y
+
+config INTEL_GPIO_PADCFG_PADTOL
+	def_bool n
+
+config INTEL_GPIO_IOSTANDBY
+	def_bool y
+
+config TPL_SIZE_LIMIT
+	default 0x7800
+
+config CPU_ADDR_BITS
+	default 39
+
+config APL_SPI_FLASH_BOOT
+	bool "Support booting with SPI-flash driver instead memory-mapped SPI"
+	select TPL_SPI_FLASH_SUPPORT
+	select TPL_SPI_SUPPORT
+	help
+	  If you want to set BOOT_FROM_FAST_SPI_FLASH to true, enable this
+	  option. It enables SPI and SPI flash in TPL. Without the this only
+	  available boot method is to use memory-mapped SPI. Since this is
+	  actually fast and produces a TPL which is 7KB smaller, it is the
+	  default.
+
+endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 106/108] x86: apollolake: Add FSP structures
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (82 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 105/108] x86: apollolake: Add Kconfig and Makefile Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 107/108] x86: apollolake: Add FSP support Simon Glass
                   ` (3 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

These are mostly specific to a particular SoC. Add the definitions for
apollolake.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add VBT signature
- Add structures for FSP-S also
- Drop struct fsp_usp_header as it is now in the API file

Changes in v2: None

 .../asm/arch-apollolake/fsp/fsp_configs.h     |  14 +
 .../asm/arch-apollolake/fsp/fsp_m_upd.h       | 123 ++++++++
 .../asm/arch-apollolake/fsp/fsp_s_upd.h       | 292 ++++++++++++++++++
 .../include/asm/arch-apollolake/fsp/fsp_vpd.h |  11 +
 4 files changed, 440 insertions(+)
 create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h
 create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h
 create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h
 create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h

diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h
new file mode 100644
index 00000000000..9185d94b2bc
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __FSP_CONFIGS_H__
+#define __FSP_CONFIGS_H__
+
+#define FSPT_UPD_SIGNATURE	0x545F4450554C5041	/* 'APLUPD_T' */
+#define FSPM_UPD_SIGNATURE	0x4D5F4450554C5041	/* 'APLUPD_M' */
+#define FSPS_UPD_SIGNATURE	0x535F4450554C5041	/* 'APLUPD_S' */
+#define VBT_SIGNATURE		0x54425624
+
+#endif
diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h
new file mode 100644
index 00000000000..e673fa9966f
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef	__ASM_ARCH_FSP_M_UDP_H
+#define	__ASM_ARCH_FSP_M_UDP_H
+
+#include <asm/fsp2/fsp_api.h>
+
+#define FSP_DRAM_CHANNELS	4
+
+struct __packed fspm_arch_upd {
+	u8	revision;
+	u8	reserved[3];
+	void	*nvs_buffer_ptr;
+	void	*stack_base;
+	u32	stack_size;
+	u32	boot_loader_tolum_size;
+	u32	boot_mode;
+	u8	reserved1[8];
+};
+
+struct __packed fsp_ram_channel {
+	u8	rank_enable;
+	u8	device_width;
+	u8	dram_density;
+	u8	option;
+	u8	odt_config;
+	u8	tristate_clk1;
+	u8	mode2_n;
+	u8	odt_levels;
+};
+
+struct __packed fsp_m_config {
+	u32	serial_debug_port_address;
+	u8	serial_debug_port_type;
+	u8	serial_debug_port_device;
+	u8	serial_debug_port_stride_size;
+	u8	mrc_fast_boot;
+	u8	igd;
+	u8	igd_dvmt50_pre_alloc;
+	u8	igd_aperture_size;
+	u8	gtt_size;
+	u8	primary_video_adaptor;
+	u8	package;
+	u8	profile;
+	u8	memory_down;
+
+	u8	ddr3_l_page_size;
+	u8	ddr3_lasr;
+	u8	scrambler_support;
+	u8	interleaved_mode;
+	u16	channel_hash_mask;
+	u16	slice_hash_mask;
+	u8	channels_slices_enable;
+	u8	min_ref_rate2x_enable;
+	u8	dual_rank_support_enable;
+	u8	rmt_mode;
+	u16	memory_size_limit;
+	u16	low_memory_max_value;
+
+	u16	high_memory_max_value;
+	u8	disable_fast_boot;
+	u8	dimm0_spd_address;
+	u8	dimm1_spd_address;
+	struct fsp_ram_channel chan[FSP_DRAM_CHANNELS];
+	u8	rmt_check_run;
+	u16	rmt_margin_check_scale_high_threshold;
+	u8	ch_bit_swizzling[FSP_DRAM_CHANNELS][32];
+	u32	msg_level_mask;
+	u8	unused_upd_space0[4];
+
+	u8	pre_mem_gpio_table_pin_num[4];
+	u32	pre_mem_gpio_table_ptr;
+	u8	pre_mem_gpio_table_entry_num;
+	u8	enhance_port8xh_decoding;
+	u8	spd_write_enable;
+	u8	mrc_data_saving;
+	u32	oem_loading_base;
+
+	u8	oem_file_name[16];
+
+	void	*mrc_boot_data_ptr;
+	u8	e_mmc_trace_len;
+	u8	skip_cse_rbp;
+	u8	npk_en;
+	u8	fw_trace_en;
+	u8	fw_trace_destination;
+	u8	recover_dump;
+	u8	msc0_wrap;
+	u8	msc1_wrap;
+	u32	msc0_size;
+
+	u32	msc1_size;
+	u8	pti_mode;
+	u8	pti_training;
+	u8	pti_speed;
+	u8	punit_mlvl;
+
+	u8	pmc_mlvl;
+	u8	sw_trace_en;
+	u8	periodic_retraining_disable;
+	u8	enable_reset_system;
+
+	u8	enable_s3_heci2;
+	u8	unused_upd_space1[3];
+
+	void	*variable_nvs_buffer_ptr;
+	u8	reserved_fspm_upd[12];
+};
+
+/** Fsp M UPD Configuration */
+struct __packed fspm_upd {
+	struct fsp_upd_header header;
+	struct fspm_arch_upd arch;
+	struct fsp_m_config config;
+	u8 unused_upd_space2[158];
+	u16 upd_terminator;
+};
+
+#endif
diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h
new file mode 100644
index 00000000000..ef908906b83
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (c) 2016, Intel Corporation. All rights reserved.
+ * Copyright 2019 Google LLC
+ */
+#ifndef __ASM_ARCH_FSP_S_UDP_H
+#define __ASM_ARCH_FSP_S_UDP_H
+
+#include <asm/fsp2/fsp_api.h>
+
+struct __packed fsp_s_config {
+	u8	active_processor_cores;
+	u8	disable_core1;
+	u8	disable_core2;
+	u8	disable_core3;
+	u8	vmx_enable;
+	u8	proc_trace_mem_size;
+	u8	proc_trace_enable;
+	u8	eist;
+	u8	boot_p_state;
+	u8	enable_cx;
+	u8	c1e;
+	u8	bi_proc_hot;
+	u8	pkg_c_state_limit;
+	u8	c_state_auto_demotion;
+	u8	c_state_un_demotion;
+	u8	max_core_c_state;
+	u8	pkg_c_state_demotion;
+	u8	pkg_c_state_un_demotion;
+	u8	turbo_mode;
+	u8	hda_verb_table_entry_num;
+	u32	hda_verb_table_ptr;
+	u8	p2sb_unhide;
+	u8	ipu_en;
+	u8	ipu_acpi_mode;
+	u8	force_wake;
+	u32	gtt_mm_adr;
+	u32	gm_adr;
+	u8	pavp_lock;
+	u8	graphics_freq_modify;
+	u8	graphics_freq_req;
+	u8	graphics_video_freq;
+	u8	pm_lock;
+	u8	dop_clock_gating;
+	u8	unsolicited_attack_override;
+	u8	wopcm_support;
+	u8	wopcm_size;
+	u8	power_gating;
+	u8	unit_level_clock_gating;
+	u8	fast_boot;
+	u8	dyn_sr;
+	u8	sa_ipu_enable;
+	u8	pm_support;
+	u8	enable_render_standby;
+	u32	logo_size;
+	u32	logo_ptr;
+	u32	graphics_config_ptr;
+	u8	pavp_enable;
+	u8	pavp_pr3;
+	u8	cd_clock;
+	u8	pei_graphics_peim_init;
+	u8	write_protection_enable[5];
+	u8	read_protection_enable[5];
+	u16	protected_range_limit[5];
+	u16	protected_range_base[5];
+	u8	gmm;
+	u8	clk_gating_pgcb_clk_trunk;
+	u8	clk_gating_sb;
+	u8	clk_gating_sb_clk_trunk;
+	u8	clk_gating_sb_clk_partition;
+	u8	clk_gating_core;
+	u8	clk_gating_dma;
+	u8	clk_gating_reg_access;
+	u8	clk_gating_host;
+	u8	clk_gating_partition;
+	u8	clk_gating_trunk;
+	u8	hda_enable;
+	u8	dsp_enable;
+	u8	pme;
+	u8	hd_audio_io_buffer_ownership;
+	u8	hd_audio_io_buffer_voltage;
+	u8	hd_audio_vc_type;
+	u8	hd_audio_link_frequency;
+	u8	hd_audio_i_disp_link_frequency;
+	u8	hd_audio_i_disp_link_tmode;
+	u8	dsp_endpoint_dmic;
+	u8	dsp_endpoint_bluetooth;
+	u8	dsp_endpoint_i2s_skp;
+	u8	dsp_endpoint_i2s_hp;
+	u8	audio_ctl_pwr_gate;
+	u8	audio_dsp_pwr_gate;
+	u8	mmt;
+	u8	hmt;
+	u8	hd_audio_pwr_gate;
+	u8	hd_audio_clk_gate;
+	u32	dsp_feature_mask;
+	u32	dsp_pp_module_mask;
+	u8	bios_cfg_lock_down;
+	u8	hpet;
+	u8	hpet_bdf_valid;
+	u8	hpet_bus_number;
+	u8	hpet_device_number;
+	u8	hpet_function_number;
+	u8	io_apic_bdf_valid;
+	u8	io_apic_bus_number;
+	u8	io_apic_device_number;
+	u8	io_apic_function_number;
+	u8	io_apic_entry24_119;
+	u8	io_apic_id;
+	u8	io_apic_range_select;
+	u8	ish_enable;
+	u8	bios_interface;
+	u8	bios_lock;
+	u8	spi_eiss;
+	u8	bios_lock_sw_smi_number;
+	u8	lpss_s0ix_enable;
+	u8	unused_upd_space0[1];
+	u8	i2c_clk_gate_cfg[8];
+	u8	hsuart_clk_gate_cfg[4];
+	u8	spi_clk_gate_cfg[3];
+	u8	i2c0_enable;
+	u8	i2c1_enable;
+	u8	i2c2_enable;
+	u8	i2c3_enable;
+	u8	i2c4_enable;
+	u8	i2c5_enable;
+	u8	i2c6_enable;
+	u8	i2c7_enable;
+	u8	hsuart0_enable;
+	u8	hsuart1_enable;
+	u8	hsuart2_enable;
+	u8	hsuart3_enable;
+	u8	spi0_enable;
+	u8	spi1_enable;
+	u8	spi2_enable;
+	u8	os_dbg_enable;
+	u8	dci_en;
+	u32	uart2_kernel_debug_base_address;
+	u8	pcie_clock_gating_disabled;
+	u8	pcie_root_port8xh_decode;
+	u8	pcie8xh_decode_port_index;
+	u8	pcie_root_port_peer_memory_write_enable;
+	u8	pcie_aspm_sw_smi_number;
+	u8	unused_upd_space1[1];
+	u8	pcie_root_port_en[6];
+	u8	pcie_rp_hide[6];
+	u8	pcie_rp_slot_implemented[6];
+	u8	pcie_rp_hot_plug[6];
+	u8	pcie_rp_pm_sci[6];
+	u8	pcie_rp_ext_sync[6];
+	u8	pcie_rp_transmitter_half_swing[6];
+	u8	pcie_rp_acs_enabled[6];
+	u8	pcie_rp_clk_req_supported[6];
+	u8	pcie_rp_clk_req_number[6];
+	u8	pcie_rp_clk_req_detect[6];
+	u8	advanced_error_reporting[6];
+	u8	pme_interrupt[6];
+	u8	unsupported_request_report[6];
+	u8	fatal_error_report[6];
+	u8	no_fatal_error_report[6];
+	u8	correctable_error_report[6];
+	u8	system_error_on_fatal_error[6];
+	u8	system_error_on_non_fatal_error[6];
+	u8	system_error_on_correctable_error[6];
+	u8	pcie_rp_speed[6];
+	u8	physical_slot_number[6];
+	u8	pcie_rp_completion_timeout[6];
+	u8	ptm_enable[6];
+	u8	pcie_rp_aspm[6];
+	u8	pcie_rp_l1_substates[6];
+	u8	pcie_rp_ltr_enable[6];
+	u8	pcie_rp_ltr_config_lock[6];
+	u8	pme_b0_s5_dis;
+	u8	pci_clock_run;
+	u8	timer8254_clk_setting;
+	u8	enable_sata;
+	u8	sata_mode;
+	u8	sata_salp_support;
+	u8	sata_pwr_opt_enable;
+	u8	e_sata_speed_limit;
+	u8	speed_limit;
+	u8	unused_upd_space2[1];
+	u8	sata_ports_enable[2];
+	u8	sata_ports_dev_slp[2];
+	u8	sata_ports_hot_plug[2];
+	u8	sata_ports_interlock_sw[2];
+	u8	sata_ports_external[2];
+	u8	sata_ports_spin_up[2];
+	u8	sata_ports_solid_state_drive[2];
+	u8	sata_ports_enable_dito_config[2];
+	u8	sata_ports_dm_val[2];
+	u8	unused_upd_space3[2];
+	u16	sata_ports_dito_val[2];
+	u16	sub_system_vendor_id;
+	u16	sub_system_id;
+	u8	crid_settings;
+	u8	reset_select;
+	u8	sdcard_enabled;
+	u8	e_mmc_enabled;
+	u8	e_mmc_host_max_speed;
+	u8	ufs_enabled;
+	u8	sdio_enabled;
+	u8	gpp_lock;
+	u8	sirq_enable;
+	u8	sirq_mode;
+	u8	start_frame_pulse;
+	u8	smbus_enable;
+	u8	arp_enable;
+	u8	unused_upd_space4;
+	u16	num_rsvd_smbus_addresses;
+	u8	rsvd_smbus_address_table[128];
+	u8	disable_compliance_mode;
+	u8	usb_per_port_ctl;
+	u8	usb30_mode;
+	u8	unused_upd_space5[1];
+	u8	port_usb20_enable[8];
+	u8	port_us20b_over_current_pin[8];
+	u8	usb_otg;
+	u8	hsic_support_enable;
+	u8	port_usb30_enable[6];
+	u8	port_us30b_over_current_pin[6];
+	u8	ssic_port_enable[2];
+	u16	dlane_pwr_gating;
+	u8	vtd_enable;
+	u8	lock_down_global_smi;
+	u16	reset_wait_timer;
+	u8	rtc_lock;
+	u8	sata_test_mode;
+	u8	ssic_rate[2];
+	u16	dynamic_power_gating;
+	u16	pcie_rp_ltr_max_snoop_latency[6];
+	u8	pcie_rp_snoop_latency_override_mode[6];
+	u8	unused_upd_space6[2];
+	u16	pcie_rp_snoop_latency_override_value[6];
+	u8	pcie_rp_snoop_latency_override_multiplier[6];
+	u8	skip_mp_init;
+	u8	dci_auto_detect;
+	u16	pcie_rp_ltr_max_non_snoop_latency[6];
+	u8	pcie_rp_non_snoop_latency_override_mode[6];
+	u8	tco_timer_halt_lock;
+	u8	pwr_btn_override_period;
+	u16	pcie_rp_non_snoop_latency_override_value[6];
+	u8	pcie_rp_non_snoop_latency_override_multiplier[6];
+	u8	pcie_rp_slot_power_limit_scale[6];
+	u8	pcie_rp_slot_power_limit_value[6];
+	u8	disable_native_power_button;
+	u8	power_butter_debounce_mode;
+	u32	sdio_tx_cmd_cntl;
+	u32	sdio_tx_data_cntl1;
+	u32	sdio_tx_data_cntl2;
+	u32	sdio_rx_cmd_data_cntl1;
+	u32	sdio_rx_cmd_data_cntl2;
+	u32	sdcard_tx_cmd_cntl;
+	u32	sdcard_tx_data_cntl1;
+	u32	sdcard_tx_data_cntl2;
+	u32	sdcard_rx_cmd_data_cntl1;
+	u32	sdcard_rx_strobe_cntl;
+	u32	sdcard_rx_cmd_data_cntl2;
+	u32	emmc_tx_cmd_cntl;
+	u32	emmc_tx_data_cntl1;
+	u32	emmc_tx_data_cntl2;
+	u32	emmc_rx_cmd_data_cntl1;
+	u32	emmc_rx_strobe_cntl;
+	u32	emmc_rx_cmd_data_cntl2;
+	u32	emmc_master_sw_cntl;
+	u8	pcie_rp_selectable_deemphasis[6];
+	u8	monitor_mwait_enable;
+	u8	hd_audio_dsp_uaa_compliance;
+	u32	ipc[4];
+	u8	sata_ports_disable_dynamic_pg[2];
+	u8	init_s3_cpu;
+	u8	skip_punit_init;
+	u8	unused_upd_space7[4];
+	u8	port_usb20_per_port_tx_pe_half[8];
+	u8	port_usb20_per_port_pe_txi_set[8];
+	u8	port_usb20_per_port_txi_set[8];
+	u8	port_usb20_hs_skew_sel[8];
+	u8	port_usb20_i_usb_tx_emphasis_en[8];
+	u8	port_usb20_per_port_rxi_set[8];
+	u8	port_usb20_hs_npre_drv_sel[8];
+	u8	reserved_fsps_upd[16];
+};
+
+/** struct fsps_upd - FSP S Configuration */
+struct __packed fsps_upd {
+	struct fsp_upd_header header;
+	struct fsp_s_config config;
+	u8 unused_upd_space2[46];
+	u16 upd_terminator;
+};
+
+#endif
diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h
new file mode 100644
index 00000000000..b14f28b2364
--- /dev/null
+++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __FSP_VPD_H
+#define __FSP_VPD_H
+
+/* Nothing to declare here for FSP2 */
+
+#endif
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 107/108] x86: apollolake: Add FSP support
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (83 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 106/108] x86: apollolake: Add FSP structures Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 108/108] x86: Add chromebook_coral Simon Glass
                   ` (2 subsequent siblings)
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

The memory and silicon init parts of the FSP need support code to work.
Add this for apollolake.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add bootstage timing for reading vbt
- Add fspm_done() hook to handle FSP-S wierdness (it breaks SPI flash)
- Don't allow BOOT_FROM_FAST_SPI_FLASH with FSP-S
- Set boot_loader_tolum_size to 0
- Use the IRQ uclass instead of ITSS

Changes in v2: None

 arch/x86/cpu/apollolake/Makefile |   6 +
 arch/x86/cpu/apollolake/fsp_m.c  | 210 ++++++++++
 arch/x86/cpu/apollolake/fsp_s.c  | 665 +++++++++++++++++++++++++++++++
 3 files changed, 881 insertions(+)
 create mode 100644 arch/x86/cpu/apollolake/fsp_m.c
 create mode 100644 arch/x86/cpu/apollolake/fsp_s.c

diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 7b040c37a72..d0cbeabaecb 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -9,6 +9,12 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o
 ifndef CONFIG_TPL_BUILD
 obj-y += cpu.o
 obj-y += punit.o
+ifdef CONFIG_SPL_BUILD
+obj-y += fsp_m.o
+endif
+endif
+ifndef CONFIG_SPL_BUILD
+obj-y += fsp_s.o
 endif
 
 obj-y += gpio.o
diff --git a/arch/x86/cpu/apollolake/fsp_m.c b/arch/x86/cpu/apollolake/fsp_m.c
new file mode 100644
index 00000000000..39cda7c49bb
--- /dev/null
+++ b/arch/x86/cpu/apollolake/fsp_m.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/fsp/fsp_configs.h>
+#include <asm/arch/fsp/fsp_m_upd.h>
+#include <asm/fsp2/fsp_internal.h>
+#include <dm/uclass-internal.h>
+
+/*
+ * ODT settings:
+ * If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A and HIGH for ODT_B,
+ * choose ODT_A_B_HIGH_HIGH. If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A
+ * and LOW for ODT_B, choose ODT_A_B_HIGH_LOW.
+ *
+ * Note that the enum values correspond to the interpreted UPD fields
+ * within Ch[3:0]_OdtConfig parameters.
+ */
+enum {
+	ODT_A_B_HIGH_LOW	= 0 << 1,
+	ODT_A_B_HIGH_HIGH	= 1 << 1,
+	N_WR_24			= 1 << 5,
+};
+
+/*
+ * LPDDR4 helper routines for configuring the memory UPD for LPDDR4 operation.
+ * There are four physical LPDDR4 channels, each 32-bits wide. There are two
+ * logical channels using two physical channels together to form a 64-bit
+ * interface to memory for each logical channel.
+ */
+
+enum {
+	LP4_PHYS_CH0A,
+	LP4_PHYS_CH0B,
+	LP4_PHYS_CH1A,
+	LP4_PHYS_CH1B,
+
+	LP4_NUM_PHYS_CHANNELS,
+};
+
+/*
+ * The DQs within a physical channel can be bit-swizzled within each byte.
+ * Within a channel the bytes can be swapped, but the DQs need to be routed
+ * with the corresponding DQS (strobe).
+ */
+enum {
+	LP4_DQS0,
+	LP4_DQS1,
+	LP4_DQS2,
+	LP4_DQS3,
+
+	LP4_NUM_BYTE_LANES,
+	DQ_BITS_PER_DQS		= 8,
+};
+
+/* Provide bit swizzling per DQS and byte swapping within a channel */
+struct lpddr4_chan_swizzle_cfg {
+	u8 dqs[LP4_NUM_BYTE_LANES][DQ_BITS_PER_DQS];
+};
+
+struct lpddr4_swizzle_cfg {
+	struct lpddr4_chan_swizzle_cfg phys[LP4_NUM_PHYS_CHANNELS];
+};
+
+static void setup_sdram(struct fsp_m_config *cfg,
+			const struct lpddr4_swizzle_cfg *swizzle_cfg)
+{
+	const struct lpddr4_chan_swizzle_cfg *sch;
+	/* Number of bytes to copy per DQS */
+	const size_t sz = DQ_BITS_PER_DQS;
+	int chan;
+
+	cfg->memory_down = 1;
+	cfg->scrambler_support = 1;
+	cfg->channel_hash_mask = 0x36;
+	cfg->slice_hash_mask = 9;
+	cfg->interleaved_mode = 2;
+	cfg->channels_slices_enable = 0;
+	cfg->min_ref_rate2x_enable = 0;
+	cfg->dual_rank_support_enable = 1;
+
+	/* LPDDR4 is memory down so no SPD addresses */
+	cfg->dimm0_spd_address = 0;
+	cfg->dimm1_spd_address = 0;
+
+	for (chan = 0; chan < 4; chan++) {
+		struct fsp_ram_channel *ch = &cfg->chan[chan];
+
+		ch->rank_enable = 1;
+		ch->device_width = 1;
+		ch->dram_density = 2;
+		ch->option = 3;
+		ch->odt_config = ODT_A_B_HIGH_HIGH;
+	}
+
+	/*
+	 * CH0_DQB byte lanes in the bit swizzle configuration field are
+	 * not 1:1. The mapping within the swizzling field is:
+	 *   indices [0:7]   - byte lane 1 (DQS1) DQ[8:15]
+	 *   indices [8:15]  - byte lane 0 (DQS0) DQ[0:7]
+	 *   indices [16:23] - byte lane 3 (DQS3) DQ[24:31]
+	 *   indices [24:31] - byte lane 2 (DQS2) DQ[16:23]
+	 */
+	sch = &swizzle_cfg->phys[LP4_PHYS_CH0B];
+	memcpy(&cfg->ch_bit_swizzling[0][0], &sch->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->ch_bit_swizzling[0][8], &sch->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->ch_bit_swizzling[0][16], &sch->dqs[LP4_DQS3], sz);
+	memcpy(&cfg->ch_bit_swizzling[0][24], &sch->dqs[LP4_DQS2], sz);
+
+	/*
+	 * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
+	 */
+	sch = &swizzle_cfg->phys[LP4_PHYS_CH0A];
+	memcpy(&cfg->ch_bit_swizzling[1][0], &sch->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->ch_bit_swizzling[1][8], &sch->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->ch_bit_swizzling[1][16], &sch->dqs[LP4_DQS2], sz);
+	memcpy(&cfg->ch_bit_swizzling[1][24], &sch->dqs[LP4_DQS3], sz);
+
+	sch = &swizzle_cfg->phys[LP4_PHYS_CH1B];
+	memcpy(&cfg->ch_bit_swizzling[2][0], &sch->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->ch_bit_swizzling[2][8], &sch->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->ch_bit_swizzling[2][16], &sch->dqs[LP4_DQS3], sz);
+	memcpy(&cfg->ch_bit_swizzling[2][24], &sch->dqs[LP4_DQS2], sz);
+
+	/*
+	 * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
+	 */
+	sch = &swizzle_cfg->phys[LP4_PHYS_CH1A];
+	memcpy(&cfg->ch_bit_swizzling[3][0], &sch->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->ch_bit_swizzling[3][8], &sch->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->ch_bit_swizzling[3][16], &sch->dqs[LP4_DQS2], sz);
+	memcpy(&cfg->ch_bit_swizzling[3][24], &sch->dqs[LP4_DQS3], sz);
+}
+
+int fspm_update_config(struct udevice *dev, struct fspm_upd *upd)
+{
+	struct fsp_m_config *cfg = &upd->config;
+	struct fspm_arch_upd *arch = &upd->arch;
+
+	arch->nvs_buffer_ptr = NULL;
+	prepare_mrc_cache(upd);
+	arch->stack_base = (void *)0xfef96000;
+	arch->boot_loader_tolum_size = 0;
+
+	arch->boot_mode = FSP_BOOT_WITH_FULL_CONFIGURATION;
+	cfg->serial_debug_port_type = 2;
+	cfg->serial_debug_port_device = 2;
+	cfg->serial_debug_port_stride_size = 2;
+	cfg->serial_debug_port_address = 0;
+
+	cfg->package = 1;
+	/* Don't enforce a memory size limit */
+	cfg->memory_size_limit = 0;
+	cfg->low_memory_max_value = 2048;  /* 2 GB */
+	/* No restrictions on memory above 4GiB */
+	cfg->high_memory_max_value = 0;
+
+	/* Always default to attempt to use saved training data */
+	cfg->disable_fast_boot = 0;
+
+	const u8 *swizzle_data;
+
+	swizzle_data = dev_read_u8_array_ptr(dev, "lpddr4-swizzle",
+					     LP4_NUM_BYTE_LANES *
+					     DQ_BITS_PER_DQS *
+					     LP4_NUM_PHYS_CHANNELS);
+	if (!swizzle_data)
+		return log_msg_ret("Cannot read swizzel data", -EINVAL);
+
+	setup_sdram(cfg, (struct lpddr4_swizzle_cfg *)swizzle_data);
+
+	cfg->pre_mem_gpio_table_ptr = 0;
+
+	cfg->profile = 0xb;
+	cfg->msg_level_mask = 0;
+
+	/* other */
+	cfg->skip_cse_rbp = 1;
+	cfg->periodic_retraining_disable = 0;
+	cfg->enable_s3_heci2 = 0;
+
+	return 0;
+}
+
+/*
+ * The FSP-M binary appears to break the SPI controller. It can be fixed by
+ * writing the BAR again, so do that here
+ */
+int fspm_done(struct udevice *dev)
+{
+	struct udevice *spi;
+	int ret;
+
+	/* Don't probe the device, since that reads the BAR */
+	ret = uclass_find_first_device(UCLASS_SPI, &spi);
+	if (ret)
+		return log_msg_ret("SPI", ret);
+	if (!spi)
+		return log_msg_ret("SPI2", -ENODEV);
+
+	dm_pci_write_config32(spi, PCI_BASE_ADDRESS_0,
+			      IOMAP_SPI_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
+
+	return 0;
+}
diff --git a/arch/x86/cpu/apollolake/fsp_s.c b/arch/x86/cpu/apollolake/fsp_s.c
new file mode 100644
index 00000000000..f4699e61009
--- /dev/null
+++ b/arch/x86/cpu/apollolake/fsp_s.c
@@ -0,0 +1,665 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <acpi_s3.h>
+#include <binman.h>
+#include <dm.h>
+#include <irq.h>
+#include <asm/io.h>
+#include <asm/intel_regs.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+#include <asm/pci.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/systemagent.h>
+#include <asm/arch/fsp/fsp_configs.h>
+#include <asm/arch/fsp/fsp_s_upd.h>
+
+#define PCH_P2SB_E0		0xe0
+#define HIDE_BIT		BIT(0)
+
+#define INTEL_GSPI_MAX		3
+#define INTEL_I2C_DEV_MAX	8
+#define APOLLOLAKE_USB2_PORT_MAX 8
+
+enum {
+	CHIPSET_LOCKDOWN_FSP = 0, /* FSP handles locking per UPDs */
+	CHIPSET_LOCKDOWN_COREBOOT, /* coreboot handles locking */
+};
+
+enum i2c_speed {
+	I2C_SPEED_STANDARD	= 100000,
+	I2C_SPEED_FAST		= 400000,
+	I2C_SPEED_FAST_PLUS	= 1000000,
+	I2C_SPEED_HIGH		= 3400000,
+	I2C_SPEED_FAST_ULTRA	= 5000000,
+};
+
+/*
+ * Timing values are in units of clock period, with the clock speed
+ * provided by the SOC in CONFIG_DRIVERS_I2C_DESIGNWARE_I2C_CLOCK_MHZ
+ * Automatic configuration is done based on requested speed, but the
+ * values may need tuned depending on the board and the number of
+ * devices present on the bus.
+ */
+struct dw_i2c_speed_config {
+	enum i2c_speed speed;
+	/* SCL high and low period count */
+	u16 scl_lcnt;
+	u16 scl_hcnt;
+	/*
+	 * SDA hold time should be 300ns in standard and fast modes
+	 * and long enough for deterministic logic level change in
+	 * fast-plus and high speed modes.
+	 *
+	 *  [15:0] SDA TX Hold Time
+	 * [23:16] SDA RX Hold Time
+	 */
+	u32 sda_hold;
+};
+
+/* Serial IRQ control. SERIRQ_QUIET is the default (0) */
+enum serirq_mode {
+	SERIRQ_QUIET,
+	SERIRQ_CONTINUOUS,
+	SERIRQ_OFF,
+};
+
+/*
+ * This I2C controller has support for 3 independent speed configs but can
+ * support both FAST_PLUS and HIGH speeds through the same set of speed
+ * config registers.  These are treated separately so the speed config values
+ * can be provided via ACPI to the OS.
+ */
+#define DW_I2C_SPEED_CONFIG_COUNT	4
+
+struct dw_i2c_bus_config {
+	/* Bus should be enabled prior to ramstage with temporary base */
+	int early_init;
+	/* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */
+	enum i2c_speed speed;
+	/*
+	 * If rise_time_ns is non-zero the calculations for lcnt and hcnt
+	 * registers take into account the times of the bus. However, if
+	 * there is a match in speed_config those register values take
+	 * precedence
+	 */
+	int rise_time_ns;
+	int fall_time_ns;
+	int data_hold_time_ns;
+	/* Specific bus speed configuration */
+	struct dw_i2c_speed_config speed_config[DW_I2C_SPEED_CONFIG_COUNT];
+};
+
+struct gspi_cfg {
+	/* Bus speed in MHz */
+	u32 speed_mhz;
+	/* Bus should be enabled prior to ramstage with temporary base */
+	u8 early_init;
+};
+
+/*
+ * This structure will hold data required by common blocks.
+ * These are soc specific configurations which will be filled by soc.
+ * We'll fill this structure once during init and use the data in common block.
+ */
+struct soc_intel_common_config {
+	int chipset_lockdown;
+	struct gspi_cfg gspi[INTEL_GSPI_MAX];
+	struct dw_i2c_bus_config i2c[INTEL_I2C_DEV_MAX];
+};
+
+enum pnp_settings {
+	PNP_PERF,
+	PNP_POWER,
+	PNP_PERF_POWER,
+};
+
+struct usb2_eye_per_port {
+	u8 Usb20PerPortTxPeHalf;
+	u8 Usb20PerPortPeTxiSet;
+	u8 Usb20PerPortTxiSet;
+	u8 Usb20HsSkewSel;
+	u8 Usb20IUsbTxEmphasisEn;
+	u8 Usb20PerPortRXISet;
+	u8 Usb20HsNpreDrvSel;
+	u8 Usb20OverrideEn;
+};
+
+struct apl_config {
+	/* Common structure containing soc config data required by common code*/
+	struct soc_intel_common_config common_soc_config;
+
+	/*
+	 * Mapping from PCIe root port to CLKREQ input on the SOC. The SOC has
+	 * four CLKREQ inputs, but six root ports. Root ports without an
+	 * associated CLKREQ signal must be marked with "CLKREQ_DISABLED"
+	 */
+	u8 pcie_rp_clkreq_pin[MAX_PCIE_PORTS];
+
+	/* Enable/disable hot-plug for root ports (0 = disable, 1 = enable) */
+	u8 pcie_rp_hotplug_enable[MAX_PCIE_PORTS];
+
+	/* De-emphasis enable configuration for each PCIe root port */
+	u8 pcie_rp_deemphasis_enable[MAX_PCIE_PORTS];
+
+	/* [14:8] DDR mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR mode Number of dealy elements.Each = 125pSec.
+	 */
+	u32 emmc_tx_cmd_cntl;
+
+	/* [14:8] HS400 mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR104/HS200 mode Number of dealy elements.Each = 125pSec.
+	 */
+	u32 emmc_tx_data_cntl1;
+
+	/* [30:24] SDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR12/Compatibility mode Number of dealy elements.
+	 *       Each = 125pSec.
+	 */
+	u32 emmc_tx_data_cntl2;
+
+	/* [30:24] SDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR12/Compatibility mode Number of dealy elements.
+	 *       Each = 125pSec.
+	 */
+	u32 emmc_rx_cmd_data_cntl1;
+
+	/* [14:8] HS400 mode 1 Number of dealy elements.Each = 125pSec.
+	 * [6:0] HS400 mode 2 Number of dealy elements.Each = 125pSec.
+	 */
+	u32 emmc_rx_strobe_cntl;
+
+	/* [13:8] Auto Tuning mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR104/HS200 Number of dealy elements.Each = 125pSec.
+	 */
+	u32 emmc_rx_cmd_data_cntl2;
+
+	/* Select the eMMC max speed allowed */
+	u32 emmc_host_max_speed;
+
+	/* Specifies on which IRQ the SCI will internally appear */
+	u32 sci_irq;
+
+	/* Configure serial IRQ (SERIRQ) line */
+	enum serirq_mode serirq_mode;
+
+	/* Configure LPSS S0ix Enable */
+	bool lpss_s0ix_enable;
+
+	/* Enable DPTF support */
+	bool dptf_enable;
+
+	/* TCC activation offset value in degrees Celsius */
+	int tcc_offset;
+
+	/* Configure Audio clk gate and power gate
+	 * IOSF-SB port ID 92 offset 0x530 [5] and [3]
+	 */
+	bool hdaudio_clk_gate_enable;
+	bool hdaudio_pwr_gate_enable;
+	bool hdaudio_bios_config_lockdown;
+
+	/* SLP S3 minimum assertion width */
+	int slp_s3_assertion_width_usecs;
+
+	/* GPIO pin for PERST_0 */
+	u32 prt0_gpio;
+
+	/* USB2 eye diagram settings per port */
+	struct usb2_eye_per_port usb2eye[APOLLOLAKE_USB2_PORT_MAX];
+
+	/* GPIO SD card detect pin */
+	unsigned int sdcard_cd_gpio;
+
+	/*
+	 * PRMRR size setting with three options
+	 *  0x02000000 - 32MiB
+	 *  0x04000000 - 64MiB
+	 *  0x08000000 - 128MiB
+	 */
+	u32 PrmrrSize;
+
+	/*
+	 * Enable SGX feature.
+	 * Enabling SGX feature is 2 step process,
+	 * (1) set sgx_enable = 1
+	 * (2) set PrmrrSize to supported size
+	 */
+	bool sgx_enable;
+
+	/*
+	 * Select PNP Settings.
+	 * (0) Performance,
+	 * (1) Power
+	 * (2) Power & Performance
+	 */
+	enum pnp_settings pnp_settings;
+
+	/*
+	 * PMIC PCH_PWROK delay configuration - IPC Configuration
+	 * Upd for changing PCH_PWROK delay configuration : I2C_Slave_Address
+	 * (31:24) + Register_Offset (23:16) + OR Value (15:8) + AND Value (7:0)
+	 */
+	u32 PmicPmcIpcCtrl;
+
+	/*
+	 * Options to disable XHCI Link Compliance Mode. Default is FALSE to not
+	 * disable Compliance Mode. Set TRUE to disable Compliance Mode.
+	 * 0:FALSE(Default), 1:True.
+	 */
+	bool DisableComplianceMode;
+
+	/*
+	 * Options to change USB3 ModPhy setting for the Integrated Filter (IF)
+	 * value. Default is 0 to not changing default IF value (0x12). Set
+	 * value with the range from 0x01 to 0xff to change IF value.
+	 */
+	u32 ModPhyIfValue;
+
+	/*
+	 * Options to bump USB3 LDO voltage. Default is FALSE to not increasing
+	 * LDO voltage. Set TRUE to increase LDO voltage with 40mV.
+	 * 0:FALSE (default), 1:True.
+	 */
+	bool ModPhyVoltageBump;
+
+	/*
+	 * Options to adjust PMIC Vdd2 voltage. Default is 0 to not adjusting
+	 * the PMIC Vdd2 default voltage 1.20v. Upd for changing Vdd2 Voltage
+	 * configuration: I2C_Slave_Address (31:23) + Register_Offset (23:16)
+	 * + OR Value (15:8) + AND Value (7:0) through BUCK5_VID[3:2]:
+	 * 00=1.10v, 01=1.15v, 10=1.24v, 11=1.20v (default).
+	 */
+	u32 PmicVdd2Voltage;
+
+	/*
+	 * Option to enable VTD feature. Default is 0 which disables VTD
+	 * capability in FSP. Setting this option to 1 in devicetree will enable
+	 * the Upd parameter VtdEnable.
+	 */
+	bool enable_vtd;
+};
+
+static int get_config(struct udevice *dev, struct apl_config *apl)
+{
+	const u8 *ptr;
+	ofnode node;
+	u32 emmc[4];
+	int ret;
+
+	memset(apl, '\0', sizeof(*apl));
+
+	node = dev_read_subnode(dev, "fsp-s");
+	if (!ofnode_valid(node))
+		return log_msg_ret("fsp-s settings", -ENOENT);
+
+	ptr = ofnode_read_u8_array_ptr(node, "pcie-rp-clkreq-pin",
+				       MAX_PCIE_PORTS);
+	if (!ptr)
+		return log_msg_ret("pcie-rp-clkreq-pin", -EINVAL);
+	memcpy(apl->pcie_rp_clkreq_pin, ptr, MAX_PCIE_PORTS);
+
+	ret = ofnode_read_u32(node, "prt0-gpio", &apl->prt0_gpio);
+	if (ret)
+		return log_msg_ret("prt0-gpio", ret);
+	ret = ofnode_read_u32(node, "sdcard-cd-gpio", &apl->sdcard_cd_gpio);
+	if (ret)
+		return log_msg_ret("sdcard-cd-gpio", ret);
+
+	ret = ofnode_read_u32_array(node, "emmc", emmc, ARRAY_SIZE(emmc));
+	if (ret)
+		return log_msg_ret("emmc", ret);
+	apl->emmc_tx_data_cntl1 = emmc[0];
+	apl->emmc_tx_data_cntl2 = emmc[1];
+	apl->emmc_rx_cmd_data_cntl1 = emmc[2];
+	apl->emmc_rx_cmd_data_cntl2 = emmc[3];
+
+	apl->dptf_enable = ofnode_read_bool(node, "dptf-enable");
+
+	apl->hdaudio_clk_gate_enable = ofnode_read_bool(node,
+						"hdaudio-clk-gate-enable");
+	apl->hdaudio_pwr_gate_enable = ofnode_read_bool(node,
+						"hdaudio-pwr-gate-enable");
+	apl->hdaudio_bios_config_lockdown = ofnode_read_bool(node,
+					     "hdaudio-bios-config-lockdown");
+	apl->lpss_s0ix_enable = ofnode_read_bool(node, "lpss-s0ix-enable");
+
+	/* Santa */
+	apl->usb2eye[1].Usb20PerPortPeTxiSet = 7;
+	apl->usb2eye[1].Usb20PerPortTxiSet = 2;
+
+	return 0;
+}
+
+static void apl_fsp_silicon_init_params_cb(struct apl_config *apl,
+					   struct fsp_s_config *cfg)
+{
+	u8 port;
+
+	for (port = 0; port < APOLLOLAKE_USB2_PORT_MAX; port++) {
+		if (apl->usb2eye[port].Usb20PerPortTxPeHalf)
+			cfg->port_usb20_per_port_tx_pe_half[port] =
+				apl->usb2eye[port].Usb20PerPortTxPeHalf;
+
+		if (apl->usb2eye[port].Usb20PerPortPeTxiSet)
+			cfg->port_usb20_per_port_pe_txi_set[port] =
+				apl->usb2eye[port].Usb20PerPortPeTxiSet;
+
+		if (apl->usb2eye[port].Usb20PerPortTxiSet)
+			cfg->port_usb20_per_port_txi_set[port] =
+				apl->usb2eye[port].Usb20PerPortTxiSet;
+
+		if (apl->usb2eye[port].Usb20HsSkewSel)
+			cfg->port_usb20_hs_skew_sel[port] =
+				apl->usb2eye[port].Usb20HsSkewSel;
+
+		if (apl->usb2eye[port].Usb20IUsbTxEmphasisEn)
+			cfg->port_usb20_i_usb_tx_emphasis_en[port] =
+				apl->usb2eye[port].Usb20IUsbTxEmphasisEn;
+
+		if (apl->usb2eye[port].Usb20PerPortRXISet)
+			cfg->port_usb20_per_port_rxi_set[port] =
+				apl->usb2eye[port].Usb20PerPortRXISet;
+
+		if (apl->usb2eye[port].Usb20HsNpreDrvSel)
+			cfg->port_usb20_hs_npre_drv_sel[port] =
+				apl->usb2eye[port].Usb20HsNpreDrvSel;
+	}
+}
+
+int fsps_update_config(struct udevice *dev, ulong rom_offset,
+		       struct fsps_upd *upd)
+{
+	struct fsp_s_config *cfg = &upd->config;
+	struct apl_config apl_cfg, *apl = &apl_cfg;
+	struct binman_entry vbt;
+	void *buf;
+	int ret;
+
+	ret = binman_entry_find("intel-vbt", &vbt);
+	if (ret)
+		return log_msg_ret("Cannot find VBT", ret);
+	vbt.image_pos += rom_offset;
+	buf = malloc(vbt.size);
+	if (!buf)
+		return log_msg_ret("Alloc VBT", -ENOMEM);
+
+	/*
+	 * Load VBT before devicetree-specific config. This only supports
+	 * memory-mapped SPI at present.
+	 */
+	bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
+	memcpy(buf, (void *)vbt.image_pos, vbt.size);
+	bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
+	if (*(u32 *)buf != VBT_SIGNATURE)
+		return log_msg_ret("VBT signature", -EINVAL);
+	cfg->graphics_config_ptr = (ulong)buf;
+
+	get_config(dev, apl);
+
+	cfg->ish_enable = 0;
+	cfg->enable_sata = 0;
+	cfg->pcie_root_port_en[2] = 0;
+	cfg->pcie_rp_hot_plug[2] = 0;
+	cfg->pcie_root_port_en[3] = 0;
+	cfg->pcie_rp_hot_plug[3] = 0;
+	cfg->pcie_root_port_en[4] = 0;
+	cfg->pcie_rp_hot_plug[4] = 0;
+	cfg->pcie_root_port_en[5] = 0;
+	cfg->pcie_rp_hot_plug[5] = 0;
+	cfg->pcie_root_port_en[1] = 0;
+	cfg->pcie_rp_hot_plug[1] = 0;
+	cfg->usb_otg = 0;
+	cfg->i2c6_enable = 0;
+	cfg->i2c7_enable = 0;
+	cfg->hsuart3_enable = 0;
+	cfg->spi1_enable = 0;
+	cfg->spi2_enable = 0;
+	cfg->sdio_enabled = 0;
+
+	memcpy(cfg->pcie_rp_clk_req_number, apl->pcie_rp_clkreq_pin,
+	       sizeof(cfg->pcie_rp_clk_req_number));
+
+	memcpy(cfg->pcie_rp_hot_plug, apl->pcie_rp_hotplug_enable,
+	       sizeof(cfg->pcie_rp_hot_plug));
+
+	switch (apl->serirq_mode) {
+	case SERIRQ_QUIET:
+		cfg->sirq_enable = 1;
+		cfg->sirq_mode = 0;
+		break;
+	case SERIRQ_CONTINUOUS:
+		cfg->sirq_enable = 1;
+		cfg->sirq_mode = 1;
+		break;
+	case SERIRQ_OFF:
+	default:
+		cfg->sirq_enable = 0;
+		break;
+	}
+
+	if (apl->emmc_tx_cmd_cntl)
+		cfg->emmc_tx_cmd_cntl = apl->emmc_tx_cmd_cntl;
+	if (apl->emmc_tx_data_cntl1)
+		cfg->emmc_tx_data_cntl1 = apl->emmc_tx_data_cntl1;
+	if (apl->emmc_tx_data_cntl2)
+		cfg->emmc_tx_data_cntl2 = apl->emmc_tx_data_cntl2;
+	if (apl->emmc_rx_cmd_data_cntl1)
+		cfg->emmc_rx_cmd_data_cntl1 = apl->emmc_rx_cmd_data_cntl1;
+	if (apl->emmc_rx_strobe_cntl)
+		cfg->emmc_rx_strobe_cntl = apl->emmc_rx_strobe_cntl;
+	if (apl->emmc_rx_cmd_data_cntl2)
+		cfg->emmc_rx_cmd_data_cntl2 = apl->emmc_rx_cmd_data_cntl2;
+	if (apl->emmc_host_max_speed)
+		cfg->e_mmc_host_max_speed = apl->emmc_host_max_speed;
+
+	cfg->lpss_s0ix_enable = apl->lpss_s0ix_enable;
+
+	/*
+	 * Disable monitor mwait since it is broken due to a hardware bug
+	 * without a fix. Specific to Apollolake.
+	 */
+	if (!IS_ENABLED(CONFIG_SOC_INTEL_GLK))
+		cfg->monitor_mwait_enable = 0;
+
+	cfg->skip_mp_init = true;
+
+	/* Disable setting of EISS bit in FSP */
+	cfg->spi_eiss = 0;
+
+	/* Disable FSP from locking access to the RTC NVRAM */
+	cfg->rtc_lock = 0;
+
+	/* Enable Audio clk gate and power gate */
+	cfg->hd_audio_clk_gate = apl->hdaudio_clk_gate_enable;
+	cfg->hd_audio_pwr_gate = apl->hdaudio_pwr_gate_enable;
+	/* Bios config lockdown Audio clk and power gate */
+	cfg->bios_cfg_lock_down = apl->hdaudio_bios_config_lockdown;
+	apl_fsp_silicon_init_params_cb(apl, cfg);
+
+	cfg->usb_otg = true;
+
+	/* Set VTD feature according to devicetree */
+	cfg->vtd_enable = apl->enable_vtd;
+
+	return 0;
+}
+
+static void p2sb_set_hide_bit(pci_dev_t dev, int hide)
+{
+	pci_x86_clrset_config(dev, PCH_P2SB_E0 + 1, HIDE_BIT,
+			      hide ? HIDE_BIT : 0, PCI_SIZE_8);
+}
+
+/* Configure package power limits */
+static int set_power_limits(struct udevice *dev)
+{
+	msr_t rapl_msr_reg, limit;
+	u32 power_unit;
+	u32 tdp, min_power, max_power;
+	u32 pl2_val;
+	u32 override_tdp[2];
+	int ret;
+
+	/* Get units */
+	rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU_UNIT);
+	power_unit = 1 << (rapl_msr_reg.lo & 0xf);
+
+	/* Get power defaults for this SKU */
+	rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU);
+	tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK;
+	pl2_val = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
+	min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK;
+	max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
+
+	if (min_power > 0 && tdp < min_power)
+		tdp = min_power;
+
+	if (max_power > 0 && tdp > max_power)
+		tdp = max_power;
+
+	ret = dev_read_u32_array(dev, "tdp-pl-override-mw", override_tdp,
+				 ARRAY_SIZE(override_tdp));
+	if (ret)
+		return log_msg_ret("tdp-pl-override-mw", ret);
+
+	/* Set PL1 override value */
+	if (override_tdp[0])
+		tdp = override_tdp[0] * power_unit / 1000;
+
+	/* Set PL2 override value */
+	if (override_tdp[1])
+		pl2_val = override_tdp[1] * power_unit / 1000;
+
+	/* Set long term power limit to TDP */
+	limit.lo = tdp & PKG_POWER_LIMIT_MASK;
+	/* Set PL1 Pkg Power clamp bit */
+	limit.lo |= PKG_POWER_LIMIT_CLAMP;
+
+	limit.lo |= PKG_POWER_LIMIT_EN;
+	limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT &
+		PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT;
+
+	/* Set short term power limit PL2 */
+	limit.hi = pl2_val & PKG_POWER_LIMIT_MASK;
+	limit.hi |= PKG_POWER_LIMIT_EN;
+
+	/* Program package power limits in RAPL MSR */
+	msr_write(MSR_PKG_POWER_LIMIT, limit);
+	log_info("RAPL PL1 %d.%dW\n", tdp / power_unit,
+		 100 * (tdp % power_unit) / power_unit);
+	log_info("RAPL PL2 %d.%dW\n", pl2_val / power_unit,
+		 100 * (pl2_val % power_unit) / power_unit);
+
+	/*
+	 * Sett RAPL MMIO register for Power limits. RAPL driver is using MSR
+	 * instead of MMIO, so disable LIMIT_EN bit for MMIO
+	 */
+	writel(limit.lo & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL));
+	writel(limit.hi & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL + 4));
+
+	return 0;
+}
+
+int p2sb_unhide(void)
+{
+	pci_dev_t dev = PCI_BDF(0, 0xd, 0);
+	ulong val;
+
+	p2sb_set_hide_bit(dev, 0);
+
+	pci_x86_read_config(dev, PCI_VENDOR_ID, &val, PCI_SIZE_16);
+
+	if (val != PCI_VENDOR_ID_INTEL)
+		return log_msg_ret("p2sb unhide", -EIO);
+
+	return 0;
+}
+
+/* Overwrites the SCI IRQ if another IRQ number is given by device tree */
+static void set_sci_irq(void)
+{
+	/* Skip this for now */
+}
+
+int arch_fsp_s_preinit(void)
+{
+	struct udevice *itss;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_IRQ, &itss);
+	if (ret)
+		return log_msg_ret("no itss", ret);
+	/*
+	 * Snapshot the current GPIO IRQ polarities. FSP is setting a default
+	 * policy that doesn't honour boards' requirements
+	 */
+	irq_snapshot_polarities(itss);
+
+	/*
+	 * Clear the GPI interrupt status and enable registers. These
+	 * registers do not get reset to default state when booting from S5.
+	 */
+	ret = gpio_gpi_clear_int_cfg();
+	if (ret)
+		return log_msg_ret("gpi_clear", ret);
+
+	return 0;
+}
+
+int arch_fsp_init_r(void)
+{
+#ifdef CONFIG_HAVE_ACPI_RESUME
+	bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
+#else
+	bool s3wake = false;
+#endif
+	struct udevice *dev, *itss;
+	int ret;
+
+	/*
+	 * This must be called before any devices are probed. Put any probing
+	 * into arch_fsp_s_preinit() above.
+	 *
+	 * We don't use BOOT_FROM_FAST_SPI_FLASH here since it will force PCI
+	 * to be probed.
+	 */
+	ret = fsp_silicon_init(s3wake, false);
+	if (ret)
+		return ret;
+
+	ret = uclass_first_device_err(UCLASS_IRQ, &itss);
+	if (ret)
+		return log_msg_ret("no itss", ret);
+	/* Restore GPIO IRQ polarities back to previous settings */
+	irq_restore_polarities(itss);
+
+	/* soc_init() */
+	ret = p2sb_unhide();
+	if (ret)
+		return log_msg_ret("unhide p2sb", ret);
+
+	/* Set RAPL MSR for Package power limits*/
+	ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
+	if (ret)
+		return log_msg_ret("Cannot get northbridge", ret);
+	set_power_limits(dev);
+
+	/*
+	 * FSP-S routes SCI to IRQ 9. With the help of this function you can
+	 * select another IRQ for SCI.
+	 */
+	set_sci_irq();
+
+	return 0;
+}
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 108/108] x86: Add chromebook_coral
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (84 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 107/108] x86: apollolake: Add FSP support Simon Glass
@ 2019-10-21  3:39 ` Simon Glass
  2019-10-21 19:15 ` [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Park, Aiden
  2019-10-28  7:12 ` Bin Meng
  87 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21  3:39 UTC (permalink / raw)
  To: u-boot

Add support for coral which is a range of apollolake-based Chromebook
released in 2017. This also includes reef released in 2016, since it is
based on the same SoC.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Ad FSP-S support
- Add CONFIG_TPL_X86_ASSUME_CPUID to reduce code size
- Add Chrome OS EC support
- Add a proper SPI node and make the SPI flash node a child
- Add bootstage support
- Add more documentation
- Add spi alias in device tree
- Disable the bootcommand since it does nothing useful on coral
- Don't enable SPI flash in TPL by default
- Drop CONFIG_SPL_NET_SUPPORT
- Drop patch '86: timer: Reduce timer code size in TPL on Intel CPUs'
- Drop patch 'dm: core: Don't include ofnode functions with of-platdata'
- Drop patch 'spi: sandbox: Add a test driver for sandbox SPI flash'
- Drop patch 'spl: Allow SPL/TPL to use of-platdata without libfdt'
- Drop patch 'x86: apollolake: Add definitions for the Intel Fast SPI interface'
- Drop patch 'x86: timer: Set up the timer in timer_early_get_count()'
- Enable video and USB3
- Reduce amount of early-pad data in TPL
- Tidy up the pad settings in the device tree
- Use a zero-based tsc timer

Changes in v2: None

 arch/x86/dts/Makefile                     |   1 +
 arch/x86/dts/chromebook_coral.dts         | 790 ++++++++++++++++++++++
 board/google/Kconfig                      |  15 +
 board/google/chromebook_coral/Kconfig     |  43 ++
 board/google/chromebook_coral/MAINTAINERS |   6 +
 board/google/chromebook_coral/Makefile    |   5 +
 board/google/chromebook_coral/coral.c     |  18 +
 configs/chromebook_coral_defconfig        | 101 +++
 doc/board/google/chromebook_coral.rst     | 238 +++++++
 drivers/i2c/dw_i2c_pci.c                  |   2 +-
 include/configs/chromebook_coral.h        |  31 +
 11 files changed, 1249 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/dts/chromebook_coral.dts
 create mode 100644 board/google/chromebook_coral/Kconfig
 create mode 100644 board/google/chromebook_coral/MAINTAINERS
 create mode 100644 board/google/chromebook_coral/Makefile
 create mode 100644 board/google/chromebook_coral/coral.c
 create mode 100644 configs/chromebook_coral_defconfig
 create mode 100644 doc/board/google/chromebook_coral.rst
 create mode 100644 include/configs/chromebook_coral.h

diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index d4bdf62be6d..be209aaaf8f 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -2,6 +2,7 @@
 
 dtb-y += bayleybay.dtb \
 	cherryhill.dtb \
+	chromebook_coral.dtb \
 	chromebook_link.dtb \
 	chromebox_panther.dtb \
 	chromebook_samus.dtb \
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts
new file mode 100644
index 00000000000..79b3e60db42
--- /dev/null
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -0,0 +1,790 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/x86-gpio.h>
+
+/include/ "skeleton.dtsi"
+/include/ "keyboard.dtsi"
+/include/ "reset.dtsi"
+/include/ "rtc.dtsi"
+/include/ "tsc_timer.dtsi"
+
+#ifdef CONFIG_CHROMEOS
+#include "chromeos-x86.dtsi"
+#include "flashmap-x86-ro.dtsi"
+#include "flashmap-16mb-rw.dtsi"
+#endif
+
+#include <asm/arch-apollolake/cpu.h>
+#include <asm/arch-apollolake/gpio_apl.h>
+#include <asm/arch-apollolake/gpio_defs.h>
+#include <asm/arch-apollolake/iomap.h>
+#include <asm/arch-apollolake/pm.h>
+
+/ {
+	model = "Google Coral";
+	compatible = "google,coral", "intel,apollolake";
+
+	aliases {
+		cros-ec0 = &cros_ec;
+		fsp = &fsp_s;
+		spi0 = &spi;
+	};
+
+	config {
+	       silent_console = <0>;
+	};
+
+	chosen {
+		stdout-path = &serial;
+	};
+
+	cpus {
+		u-boot,dm-pre-reloc;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			u-boot,dm-pre-reloc;
+			device_type = "cpu";
+			compatible = "intel,apl-cpu";
+			reg = <0>;
+			intel,apic-id = <0>;
+		};
+
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "intel,apl-cpu";
+			reg = <1>;
+			intel,apic-id = <1>;
+		};
+
+		cpu at 2 {
+			device_type = "cpu";
+			compatible = "intel,apl-cpu";
+			reg = <2>;
+			intel,apic-id = <2>;
+		};
+
+		cpu at 3 {
+			device_type = "cpu";
+			compatible = "intel,apl-cpu";
+			reg = <3>;
+			intel,apic-id = <3>;
+		};
+
+	};
+
+	keyboard {
+		intel,duplicate-por;
+	};
+
+	pci {
+		compatible = "pci-x86";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		u-boot,dm-pre-reloc;
+		ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0 0x10000000
+			0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000
+			0x01000000 0x0 0x1000 0x1000 0 0xefff>;
+
+		host_bridge: host-bridge at 0,0 {
+			u-boot,dm-pre-reloc;
+			reg = <0x00000000 0 0 0 0>;
+			compatible = "intel,apl-hostbridge";
+			pciex-region-size = <0x10000000>;
+			/*
+			 * Parameters used by the FSP-S binary blob. This is
+			 * really unfortunate since these parameters mostly
+			 * relate to drivers but we need them in one place. We
+			 * could put them in the driver nodes easily, but then
+			 * would have to scan each node to find them. So just
+			 * dump them here for now.
+			 */
+			fsp_s: fsp-s {
+			};
+		};
+
+		punit at 0,1 {
+			u-boot,dm-pre-reloc;
+			reg = <0x00000800 0 0 0 0>;
+			compatible = "intel,apl-punit";
+		};
+
+		p2sb: p2sb at d,0 {
+			u-boot,dm-pre-reloc;
+			reg = <0x02006810 0 0 0 0>;
+			compatible = "intel,apl-p2sb";
+			early-regs = <IOMAP_P2SB_BAR 0x100000>;
+
+			gpio_n: n {
+				compatible = "intel,apl-gpio";
+				intel,p2sb-port-id = <PID_GPIO_N>;
+			};
+
+			nw {
+				u-boot,dm-pre-reloc;
+				compatible = "intel,apl-gpio";
+				intel,p2sb-port-id = <PID_GPIO_NW>;
+			};
+
+			w {
+				u-boot,dm-pre-reloc;
+				compatible = "intel,apl-gpio";
+				intel,p2sb-port-id = <PID_GPIO_W>;
+			};
+
+			sw {
+				u-boot,dm-pre-reloc;
+				compatible = "intel,apl-gpio";
+				intel,p2sb-port-id = <PID_GPIO_SW>;
+			};
+
+			itss {
+				u-boot,dm-pre-reloc;
+				compatible = "intel,apl-itss";
+				intel,p2sb-port-id = <PID_ITSS>;
+				intel,pmc-routes = <
+					PMC_GPE_SW_31_0 GPIO_GPE_SW_31_0
+					PMC_GPE_SW_63_32 GPIO_GPE_SW_63_32
+					PMC_GPE_NW_31_0 GPIO_GPE_NW_31_0
+					PMC_GPE_NW_63_32 GPIO_GPE_NW_63_32
+					PMC_GPE_NW_95_64 GPIO_GPE_NW_95_64
+					PMC_GPE_N_31_0 GPIO_GPE_N_31_0
+					PMC_GPE_N_63_32 GPIO_GPE_N_63_32
+					PMC_GPE_W_31_0 GPIO_GPE_W_31_0>;
+			};
+		};
+
+		pmc at d,1 {
+			u-boot,dm-pre-reloc;
+			reg = <0x6900 0 0 0 0>;
+
+			/*
+			 * Values for BAR0, BAR2 and ACPI_BASE for when PCI
+			 * auto-configure is not available
+			 */
+			early-regs = <0xfe042000 0x2000
+				0xfe044000 0x2000
+				0x400 0x100>;
+			compatible = "intel,apl-pmc";
+			gpe0-dwx-mask = <0xf>;
+			gpe0-dwx-shift-base = <4>;
+
+			/*
+			 * GPE configuration
+			 * Note that GPE events called out in ASL code rely on
+			 * this route, i.e., if this route changes then the
+			 * affected GPE * offset bits also need to be changed.
+			 * This sets the PMC register GPE_CFG fields.
+			 */
+			gpe0-dw = <PMC_GPE_N_31_0
+				PMC_GPE_N_63_32
+				PMC_GPE_SW_31_0>;
+			gpe0-sts = <0x20>;
+			gpe0-en = <0x30>;
+		};
+
+		spi: fast-spi at d,2 {
+			u-boot,dm-pre-reloc;
+			reg = <0x02006a10 0 0 0 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,fast-spi";
+			early-regs = <IOMAP_SPI_BASE 0x1000>;
+			intel,hardware-seq = <1>;
+
+			spi-flash at 0 {
+				#size-cells = <1>;
+				#address-cells = <1>;
+				u-boot,dm-pre-reloc;
+				reg = <0>;
+				compatible = "winbond,w25q128fw",
+					 "jedec,spi-nor";
+				rw-mrc-cache {
+					label = "rw-mrc-cache";
+					reg = <0x003e0000 0x00010000>;
+					u-boot,dm-pre-reloc;
+				};
+				rw-var-mrc-cache {
+					label = "rw-mrc-cache";
+					reg = <0x003f0000 0x0001000>;
+					u-boot,dm-pre-reloc;
+				};
+			};
+		};
+
+		serial: serial at 18,2 {
+			reg = <0x0200c210 0 0 0 0>;
+			u-boot,dm-pre-reloc;
+			compatible = "intel,apl-ns16550";
+			early-regs = <0xde000000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <1843200>;
+			current-speed = <115200>;
+		};
+
+		pch: pch at 1f,0 {
+			reg = <0x0000f800 0 0 0 0>;
+			compatible = "intel,apl-pch";
+			u-boot,dm-pre-reloc;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			lpc {
+				compatible = "intel,apl-lpc";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				u-boot,dm-pre-reloc;
+				cros_ec: cros-ec {
+					u-boot,dm-pre-reloc;
+					compatible = "google,cros-ec-lpc";
+					reg = <0x204 1 0x200 1 0x880 0x80>;
+
+					/*
+					 * Describes the flash memory within
+					 * the EC
+					 */
+					#address-cells = <1>;
+					#size-cells = <1>;
+					flash at 8000000 {
+						reg = <0x08000000 0x20000>;
+						erase-value = <0xff>;
+					};
+				};
+			};
+		};
+	};
+
+};
+
+&gpio_n {
+	u-boot,dm-pre-reloc;
+};
+
+&host_bridge {
+	/*
+	 * PL1 override 12000 mW: the energy calculation is wrong with the
+	 * current VR solution. Experiments show that SoC TDP max (6W) can be
+	 * reached when RAPL PL1 is set to 12W. Set RAPL PL2 to 15W.
+	 */
+	tdp-pl-override-mw = <12000 15000>;
+
+	early-pads = <
+		/* These two are for the debug UART */
+		GPIO_46 /* UART2 RX */
+			(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
+			(PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
+
+		GPIO_47 /* UART2 TX */
+			(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
+			(PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
+
+		GPIO_75 /* I2S1_BCLK -- PCH_WP */
+			(PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP)
+			(PAD_CFG1_PULL_UP_20K | PAD_CFG1_IOSSTATE_TXD_RXE)
+
+		/* I2C2 - TPM  */
+		GPIO_128 /* LPSS_I2C2_SDA */
+			(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
+			(PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
+		GPIO_129 /* LPSS_I2C2_SCL */
+			(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
+			(PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
+		GPIO_28 /* TPM IRQ */
+			(PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP |
+				PAD_CFG0_TX_DISABLE | PAD_CFG0_ROUTE_IOAPIC |
+				PAD_CFG0_TRIG_LEVEL | PAD_CFG0_RX_POL_INVERT)
+			(PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TXD_RXE)
+
+		/*
+		 * WLAN_PE_RST - default to deasserted just in case FSP
+		 * misbehaves
+		 */
+		GPIO_122  /* SIO_SPI_2_RXD */
+			(PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP |
+				PAD_CFG0_RX_DISABLE | 0)
+			(PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
+		>;
+
+	lpddr4-swizzle = /bits/ 8 <
+		/* LP4_PHYS_CH0A */
+
+		/* DQA[0:7] pins of LPDDR4 module */
+		6 7 5 4 3 1 0 2
+		/* DQA[8:15] pins of LPDDR4 module */
+		12 10 11 13 14 8 9 15
+		/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
+		16 22 23 20 18 17 19 21
+		/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
+		30 28 29 25 24 26 27 31
+
+		/* LP4_PHYS_CH0B */
+		/* DQA[0:7] pins of LPDDR4 module */
+		7 3 5 2 6 0 1 4
+		/* DQA[8:15] pins of LPDDR4 module */
+		 9 14 12 13 10 11 8 15
+		/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
+		20 22 23 16 19 17 18 21
+		/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
+		28 24 26 27 29 30 31 25
+
+		/* LP4_PHYS_CH1A */
+
+		/* DQA[0:7] pins of LPDDR4 module */
+		2 1 6 7 5 4 3 0
+		/* DQA[8:15] pins of LPDDR4 module */
+		11 10 8 9 12 15 13 14
+		/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
+		17 23 19 16 21 22 20 18
+		/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
+		31 29 26 25 28 27 24 30
+
+		/* LP4_PHYS_CH1B */
+
+		/* DQA[0:7] pins of LPDDR4 module */
+		4 3 7 5 6 1 0 2
+		/* DQA[8:15] pins of LPDDR4 module */
+		15 9 8 11 14 13 12 10
+		/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
+		20 23 22 21 18 19 16 17
+		/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
+		25 28 30 31 26 27 24 29>;
+};
+
+&fsp_s {
+	u-boot,dm-pre-proper;
+
+	/* Disable unused clkreq of PCIe root ports */
+	pcie-rp-clkreq-pin = /bits/ 8 <0 /* wifi/bt */
+		CLKREQ_DISABLED
+		CLKREQ_DISABLED
+		CLKREQ_DISABLED
+		CLKREQ_DISABLED
+		CLKREQ_DISABLED>;
+
+	/*
+	 * GPIO for PERST_0
+	 * If the Board has PERST_0 signal, assign the GPIO
+	 * If the Board does not have PERST_0, assign GPIO_PRT0_UDEF
+	 */
+	prt0-gpio = <GPIO_122>;
+	/* GPIO for SD card detect */
+	sdcard-cd-gpio = <GPIO_177>;
+
+	/*
+	 * Order is emmc-tx-data-cntl1, emmc-tx-data-cntl2,
+	 * emmc-rx-cmd-data-cntl1, emmc-rx-cmd-data-cntl2
+	 *
+	 * EMMC TX DATA Delay 1
+	 * Refer to EDS-Vol2-22.3
+	 * [14:8] steps of delay for HS400, each 125ps
+	 * [6:0] steps of delay for SDR104/HS200, each 125ps
+
+	/*
+	 * EMMC TX DATA Delay 2
+	 * Refer to EDS-Vol2-22.3.
+	 * [30:24] steps of delay for SDR50, each 125ps
+	 * [22:16] steps of delay for DDR50, each 125ps
+	 * [14:8] steps of delay for SDR25/HS50, each 125ps
+	 * [6:0] steps of delay for SDR12, each 125ps
+	 */
+
+	/*
+	 * EMMC RX CMD/DATA Delay 1
+	 * Refer to EDS-Vol2-22.3.
+	 * [30:24] steps of delay for SDR50, each 125ps
+	 * [22:16] steps of delay for DDR50, each 125ps
+	 * [14:8] steps of delay for SDR25/HS50, each 125ps
+	 * [6:0] steps of delay for SDR12, each 125ps
+	 */
+
+	/*
+	 * EMMC RX CMD/DATA Delay 2
+	 * Refer to EDS-Vol2-22.3.
+	 * [17:16] stands for Rx Clock before Output Buffer
+	 * [14:8] steps of delay for Auto Tuning Mode, each 125ps
+	 * [6:0] steps of delay for HS200, each 125ps
+	 */
+	emmc = <0x0c16 0x28162828 0x00181717 0x10008>;
+
+	/* Enable DPTF */
+	dptf-enable;
+
+	/* Enable Audio Clock and Power gating */
+	hdaudio-clk-gate-enable;
+	hdaudio-pwr-gate-enable;
+	hdaudio-bios-config-lockdown;
+
+	/* Enable lpss s0ix */
+	lpss-s0ix-enable;
+
+	/*
+	 * TODO(sjg at chromium.org): Move this to the I2C nodes
+	 * Intel Common SoC Config
+	 *+-------------------+---------------------------+
+	 *| Field             |  Value                    |
+	 *+-------------------+---------------------------+
+	 *| I2C0              | Audio                     |
+	 *| I2C2              | TPM                       |
+	 *| I2C3              | Touchscreen               |
+	 *| I2C4              | Trackpad                  |
+	 *| I2C5              | Digitizer                 |
+	 *+-------------------+---------------------------+
+	 *
+	common_soc_config" = "{
+		.i2c[0] = {
+			.speed = I2C_SPEED_FAST,
+			.rise_time_ns = 104,
+			.fall_time_ns = 52,
+		},
+		.i2c[2] = {
+			.early_init = 1,
+			.speed = I2C_SPEED_FAST,
+			.rise_time_ns = 57,
+			.fall_time_ns = 28,
+		},
+		.i2c[3] = {
+			.speed = I2C_SPEED_FAST,
+			.rise_time_ns = 76,
+			.fall_time_ns = 164,
+		},
+		.i2c[4] = {
+			.speed = I2C_SPEED_FAST,
+			.rise_time_ns = 114,
+			.fall_time_ns = 164,
+			.data_hold_time_ns = 350,
+		},
+		.i2c[5] = {
+			.speed = I2C_SPEED_FAST,
+			.rise_time_ns = 152,
+			.fall_time_ns = 30,
+		},
+	}"
+	*/
+
+	/* Minimum SLP S3 assertion width 28ms */
+	slp_s3_assertion_width_usecs = <28000>;
+
+	pads = <
+		/* PCIE_WAKE[0:3]_N */
+		PAD_CFG_GPI_SCI_LOW(GPIO_205, UP_20K, DEEP, EDGE_SINGLE) /* WLAN */
+		PAD_CFG_GPI(GPIO_206, UP_20K, DEEP)	 /* Unused */
+		PAD_CFG_GPI(GPIO_207, UP_20K, DEEP)	 /* Unused */
+		PAD_CFG_GPI(GPIO_208, UP_20K, DEEP)	 /* Unused */
+
+		/* EMMC interface */
+		PAD_CFG_NF(GPIO_156, DN_20K, DEEP, NF1) /* EMMC_CLK */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_157, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D0 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_158, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D1 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_159, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D2 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_160, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D3 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_161, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D4 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_162, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D5 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_163, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D6 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_164, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D7 */
+		PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_165, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_CMD */
+		PAD_CFG_NF(GPIO_182, DN_20K, DEEP, NF1) /* EMMC_RCLK */
+
+		/* SDIO -- unused */
+		PAD_CFG_GPI(GPIO_166, UP_20K, DEEP)	 /* SDIO_CLK */
+		PAD_CFG_GPI(GPIO_167, UP_20K, DEEP)	 /* SDIO_D0 */
+		/* Configure SDIO to enable power gating */
+		PAD_CFG_NF(GPIO_168, UP_20K, DEEP, NF1)	/* SDIO_D1 */
+		PAD_CFG_GPI(GPIO_169, UP_20K, DEEP)	 /* SDIO_D2 */
+		PAD_CFG_GPI(GPIO_170, UP_20K, DEEP)	 /* SDIO_D3 */
+		PAD_CFG_GPI(GPIO_171, UP_20K, DEEP)	 /* SDIO_CMD */
+
+		/* SDCARD */
+		/* Pull down clock by 20K */
+		PAD_CFG_NF(GPIO_172, DN_20K, DEEP, NF1) /* SDCARD_CLK */
+		PAD_CFG_NF(GPIO_173, UP_20K, DEEP, NF1) /* SDCARD_D0 */
+		PAD_CFG_NF(GPIO_174, UP_20K, DEEP, NF1) /* SDCARD_D1 */
+		PAD_CFG_NF(GPIO_175, UP_20K, DEEP, NF1) /* SDCARD_D2 */
+		PAD_CFG_NF(GPIO_176, UP_20K, DEEP, NF1) /* SDCARD_D3 */
+		/* Card detect is active LOW with external pull up */
+		PAD_CFG_NF(GPIO_177, NONE, DEEP, NF1) /* SDCARD_CD_N */
+		PAD_CFG_NF(GPIO_178, UP_20K, DEEP, NF1) /* SDCARD_CMD */
+		/* CLK feedback, internal signal, needs 20K pull down */
+		PAD_CFG_NF(GPIO_179, DN_20K, DEEP, NF1) /* SDCARD_CLK_FB */
+		/* No h/w write proect for uSD cards, pull down by 20K */
+		PAD_CFG_NF(GPIO_186, DN_20K, DEEP, NF1) /* SDCARD_LVL_WP */
+		/* EN_SD_SOCKET_PWR_L for SD slot power control. Default on */
+		PAD_CFG_GPO(GPIO_183, 0, DEEP)		 /* SDIO_PWR_DOWN_N */
+
+		/* SMBus -- unused */
+		PAD_CFG_GPI(SMB_ALERTB, UP_20K, DEEP)	 /* SMB_ALERT _N */
+		PAD_CFG_GPI(SMB_CLK, UP_20K, DEEP)	 /* SMB_CLK */
+		PAD_CFG_GPI(SMB_DATA, UP_20K, DEEP)	 /* SMB_DATA */
+
+		/* LPC */
+		PAD_CFG_NF(LPC_ILB_SERIRQ, UP_20K, DEEP, NF1) /* LPC_SERIRQ */
+		PAD_CFG_NF(LPC_CLKOUT0, NONE, DEEP, NF1) /* LPC_CLKOUT0 */
+		PAD_CFG_NF(LPC_CLKOUT1, UP_20K, DEEP, NF1)
+		PAD_CFG_NF(LPC_AD0, UP_20K, DEEP, NF1)	 /* LPC_AD0 */
+		PAD_CFG_NF(LPC_AD1, UP_20K, DEEP, NF1)	 /* LPC_AD1 */
+		PAD_CFG_NF(LPC_AD2, UP_20K, DEEP, NF1)	 /* LPC_AD2 */
+		PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1)	 /* LPC_AD3 */
+		PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */
+		PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */
+
+		/* I2C0 - Audio */
+		PAD_CFG_NF(GPIO_124, UP_2K, DEEP, NF1) /* LPSS_I2C0_SDA */
+		PAD_CFG_NF(GPIO_125, UP_2K, DEEP, NF1) /* LPSS_I2C0_SCL */
+
+		/* I2C1 - NFC with external pulls */
+		PAD_CFG_NF(GPIO_126, NONE, DEEP, NF1) /* LPSS_I2C1_SDA */
+		PAD_CFG_NF(GPIO_127, NONE, DEEP, NF1) /* LPSS_I2C1_SCL */
+
+		/* I2C2 - TPM  */
+		PAD_CFG_NF(GPIO_128, UP_2K, DEEP, NF1) /* LPSS_I2C2_SDA */
+		PAD_CFG_NF(GPIO_129, UP_2K, DEEP, NF1) /* LPSS_I2C2_SCL */
+
+		/* I2C3 - touch */
+		PAD_CFG_NF(GPIO_130, UP_2K, DEEP, NF1) /* LPSS_I2C3_SDA */
+		PAD_CFG_NF(GPIO_131, UP_2K, DEEP, NF1) /* LPSS_I2C3_SCL */
+
+		/* I2C4 - trackpad */
+		/* LPSS_I2C4_SDA */
+		PAD_CFG_NF_IOSSTATE(GPIO_132, UP_2K, DEEP, NF1, HIZCRX1)
+		/* LPSS_I2C4_SCL */
+		PAD_CFG_NF_IOSSTATE(GPIO_133, UP_2K, DEEP, NF1, HIZCRX1)
+
+		/* I2C5 -- pen with external pulls  */
+		PAD_CFG_NF(GPIO_134, NONE, DEEP, NF1) /* LPSS_I2C5_SDA */
+		PAD_CFG_NF(GPIO_135, NONE, DEEP, NF1) /* LPSS_I2C5_SCL */
+
+		/* I2C6-7 -- unused */
+		PAD_CFG_GPI(GPIO_136, UP_20K, DEEP)	 /* LPSS_I2C6_SDA */
+		PAD_CFG_GPI(GPIO_137, UP_20K, DEEP)	 /* LPSS_I2C6_SCL */
+		PAD_CFG_GPI(GPIO_138, UP_20K, DEEP)	 /* LPSS_I2C7_SDA */
+		PAD_CFG_GPI(GPIO_139, UP_20K, DEEP)	 /* LPSS_I2C7_SCL */
+
+		/* Audio Amp - I2S6 */
+		PAD_CFG_NF(GPIO_146, NATIVE, DEEP, NF2) /* ISH_GPIO_0 - I2S6_BCLK */
+		PAD_CFG_NF(GPIO_147, NATIVE, DEEP, NF2) /* ISH_GPIO_1 - I2S6_WS_SYNC */
+		PAD_CFG_GPI(GPIO_148, UP_20K, DEEP)	 /* ISH_GPIO_2 - unused */
+		PAD_CFG_NF(GPIO_149, NATIVE, DEEP, NF2) /* ISH_GPIO_3 - I2S6_SDO */
+
+		/* NFC Reset */
+		PAD_CFG_GPO(GPIO_150, 1, DEEP)		 /* ISH_GPIO_4 */
+
+		PAD_CFG_GPI(GPIO_151, UP_20K, DEEP)	 /* ISH_GPIO_5 - unused */
+
+		/* Touch enable */
+		PAD_CFG_GPO(GPIO_152, 1, DEEP)		 /* ISH_GPIO_6 */
+
+		PAD_CFG_GPI(GPIO_153, UP_20K, DEEP)	 /* ISH_GPIO_7 - unused */
+		PAD_CFG_GPI(GPIO_154, UP_20K, DEEP)	 /* ISH_GPIO_8 - unused */
+		PAD_CFG_GPI(GPIO_155, UP_20K, DEEP)	 /* ISH_GPIO_9 - unused */
+
+		/* PCIE_CLKREQ[0:3]_N */
+		PAD_CFG_NF(GPIO_209, NONE, DEEP, NF1)	 /* WLAN with external pull */
+		PAD_CFG_GPI(GPIO_210, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_211, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_212, UP_20K, DEEP)	 /* unused */
+
+		/* OSC_CLK_OUT_[0:4] -- unused */
+		PAD_CFG_GPI(OSC_CLK_OUT_0, UP_20K, DEEP)
+		PAD_CFG_GPI(OSC_CLK_OUT_1, UP_20K, DEEP)
+		PAD_CFG_GPI(OSC_CLK_OUT_2, UP_20K, DEEP)
+		PAD_CFG_GPI(OSC_CLK_OUT_3, UP_20K, DEEP)
+		PAD_CFG_GPI(OSC_CLK_OUT_4, UP_20K, DEEP)
+
+		/* PMU Signals */
+		PAD_CFG_GPI(PMU_AC_PRESENT, UP_20K, DEEP) /* PMU_AC_PRESENT - unused */
+		PAD_CFG_NF(PMU_BATLOW_B, UP_20K, DEEP, NF1) /* PMU_BATLOW_N */
+		PAD_CFG_NF(PMU_PLTRST_B, NONE, DEEP, NF1) /* PMU_PLTRST_N */
+		PAD_CFG_NF(PMU_PWRBTN_B, UP_20K, DEEP, NF1) /* PMU_PWRBTN_N */
+		PAD_CFG_NF(PMU_RESETBUTTON_B, NONE, DEEP, NF1) /* PMU_RSTBTN_N */
+		PAD_CFG_NF_IOSSTATE(PMU_SLP_S0_B, NONE, DEEP, NF1, IGNORE) /* PMU_SLP_S0_N */
+		PAD_CFG_NF(PMU_SLP_S3_B, NONE, DEEP, NF1) /* PMU_SLP_S3_N */
+		PAD_CFG_NF(PMU_SLP_S4_B, NONE, DEEP, NF1) /* PMU_SLP_S4_N */
+		PAD_CFG_NF(PMU_SUSCLK, NONE, DEEP, NF1) /* PMU_SUSCLK */
+		PAD_CFG_GPO(PMU_WAKE_B, 1, DEEP)	 /* EN_PP3300_EMMC */
+		PAD_CFG_NF(SUS_STAT_B, NONE, DEEP, NF1) /* SUS_STAT_N */
+		PAD_CFG_NF(SUSPWRDNACK, NONE, DEEP, NF1) /* SUSPWRDNACK */
+
+		/* DDI[0:1] SDA and SCL -- unused */
+		PAD_CFG_GPI(GPIO_187, UP_20K, DEEP)	 /* HV_DDI0_DDC_SDA */
+		PAD_CFG_GPI(GPIO_188, UP_20K, DEEP)	 /* HV_DDI0_DDC_SCL */
+		PAD_CFG_GPI(GPIO_189, UP_20K, DEEP)	 /* HV_DDI1_DDC_SDA */
+		PAD_CFG_GPI(GPIO_190, UP_20K, DEEP)	 /* HV_DDI1_DDC_SCL */
+
+		/* MIPI I2C -- unused */
+		PAD_CFG_GPI(GPIO_191, UP_20K, DEEP)	 /* MIPI_I2C_SDA */
+		PAD_CFG_GPI(GPIO_192, UP_20K, DEEP)	 /* MIPI_I2C_SCL */
+
+		/* Panel 0 control */
+		PAD_CFG_NF(GPIO_193, NATIVE, DEEP, NF1) /* PNL0_VDDEN */
+		PAD_CFG_NF(GPIO_194, NATIVE, DEEP, NF1) /* PNL0_BKLTEN */
+		PAD_CFG_NF(GPIO_195, NATIVE, DEEP, NF1) /* PNL0_BKLTCTL */
+
+		/* Panel 1 control -- unused */
+		PAD_CFG_NF(GPIO_196, NATIVE, DEEP, NF1) /* PNL1_VDDEN */
+		PAD_CFG_NF(GPIO_197, NATIVE, DEEP, NF1) /* PNL1_BKLTEN */
+		PAD_CFG_NF(GPIO_198, NATIVE, DEEP, NF1) /* PNL1_BKLTCTL */
+
+		/* Hot plug detect */
+		PAD_CFG_NF(GPIO_199, UP_20K, DEEP, NF2) /* HV_DDI1_HPD */
+		PAD_CFG_NF(GPIO_200, UP_20K, DEEP, NF2) /* HV_DDI0_HPD */
+
+		/* MDSI signals -- unused */
+		PAD_CFG_GPI(GPIO_201, UP_20K, DEEP)	 /* MDSI_A_TE */
+		PAD_CFG_GPI(GPIO_202, UP_20K, DEEP)	 /* MDSI_A_TE */
+
+		/* USB overcurrent pins */
+		PAD_CFG_NF(GPIO_203, UP_20K, DEEP, NF1) /* USB_OC0_N */
+		PAD_CFG_NF(GPIO_204, UP_20K, DEEP, NF1) /* USB_OC1_N */
+
+		/* PMC SPI -- almost entirely unused */
+		PAD_CFG_GPI(PMC_SPI_FS0, UP_20K, DEEP)
+		PAD_CFG_NF(PMC_SPI_FS1, UP_20K, DEEP, NF2) /* HV_DDI2_HPD -- EDP HPD */
+		PAD_CFG_GPI(PMC_SPI_FS2, UP_20K, DEEP)
+		PAD_CFG_GPI(PMC_SPI_RXD, UP_20K, DEEP)
+		PAD_CFG_GPI(PMC_SPI_TXD, UP_20K, DEEP)
+		PAD_CFG_GPI(PMC_SPI_CLK, UP_20K, DEEP)
+
+		/* PMIC Signals Unused signals related to an old PMIC interface */
+		PAD_CFG_NF_IOSSTATE(PMIC_RESET_B, NATIVE, DEEP, NF1, IGNORE) /* PMIC_RESET_B */
+		PAD_CFG_GPI(GPIO_213, NONE, DEEP)	 /* unused external pull */
+		PAD_CFG_GPI(GPIO_214, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_215, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_NF(PMIC_THERMTRIP_B, UP_20K, DEEP, NF1) /* THERMTRIP_N */
+		PAD_CFG_GPI(PMIC_STDBY, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_NF(PROCHOT_B, UP_20K, DEEP, NF1) /* PROCHOT_N */
+		PAD_CFG_NF(PMIC_I2C_SCL, UP_1K, DEEP, NF1) /* PMIC_I2C_SCL */
+		PAD_CFG_NF(PMIC_I2C_SDA, UP_1K, DEEP, NF1) /* PMIC_I2C_SDA */
+
+		/* I2S1 -- largely unused */
+		PAD_CFG_GPI(GPIO_74, UP_20K, DEEP)	/* I2S1_MCLK */
+		PAD_CFG_GPI(GPIO_75, UP_20K, DEEP)	/* I2S1_BCLK -- PCH_WP */
+		PAD_CFG_GPO(GPIO_76, 0, DEEP)		/* I2S1_WS_SYNC -- SPK_PA_EN */
+		PAD_CFG_GPI(GPIO_77, UP_20K, DEEP)	/* I2S1_SDI */
+		PAD_CFG_GPO(GPIO_78, 1, DEEP)		/* I2S1_SDO -- EN_PP3300_DX_LTE_SOC */
+
+		/* DMIC or I2S4 */
+		/* AVS_DMIC_CLK_A1 */
+		PAD_CFG_NF_IOSSTATE(GPIO_79, NATIVE, DEEP, NF1, IGNORE)
+		PAD_CFG_NF(GPIO_80, NATIVE, DEEP, NF1) /* AVS_DMIC_CLK_B1 */
+		PAD_CFG_NF(GPIO_81, NATIVE, DEEP, NF1)	/* AVS_DMIC_DATA_1 */
+		PAD_CFG_GPI(GPIO_82, DN_20K, DEEP)	 /* unused -- strap */
+		PAD_CFG_NF(GPIO_83, NATIVE, DEEP, NF1) /* AVS_DMIC_DATA_2 */
+
+		/* I2S2 -- Headset amp */
+		PAD_CFG_NF(GPIO_84, NATIVE, DEEP, NF1)	 /* AVS_I2S2_MCLK */
+		PAD_CFG_NF(GPIO_85, NATIVE, DEEP, NF1)	 /* AVS_I2S2_BCLK */
+		PAD_CFG_NF(GPIO_86, NATIVE, DEEP, NF1)	 /* AVS_I2S2_SW_SYNC */
+		PAD_CFG_NF(GPIO_87, NATIVE, DEEP, NF1)	 /* AVS_I2S2_SDI */
+		PAD_CFG_NF(GPIO_88, NATIVE, DEEP, NF1)	 /* AVS_I2S2_SDO */
+
+		/* I2S3 -- largely unused */
+		PAD_CFG_GPI(GPIO_89, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_90, UP_20K, DEEP)	 /* GPS_HOST_WAKE */
+		PAD_CFG_GPO(GPIO_91, 1, DEEP)		 /* GPS_EN */
+		PAD_CFG_GPI(GPIO_92, DN_20K, DEEP)	 /* unused -- strap */
+
+		/* Fast SPI */
+		PAD_CFG_NF_IOSSTATE(GPIO_97, NATIVE, DEEP, NF1, IGNORE)	/* FST_SPI_CS0_B */
+		PAD_CFG_GPI(GPIO_98, UP_20K, DEEP)				/* FST_SPI_CS1_B -- unused */
+		PAD_CFG_NF_IOSSTATE(GPIO_99, NATIVE, DEEP, NF1, IGNORE)	/* FST_SPI_MOSI_IO0 */
+		PAD_CFG_NF_IOSSTATE(GPIO_100, NATIVE, DEEP, NF1, IGNORE)	/* FST_SPI_MISO_IO1 */
+		PAD_CFG_GPI(GPIO_101, NONE, DEEP)				/* FST_IO2 -- MEM_CONFIG0 */
+		PAD_CFG_GPI(GPIO_102, NONE, DEEP)				/* FST_IO3 -- MEM_CONFIG1 */
+		PAD_CFG_NF_IOSSTATE(GPIO_103, NATIVE, DEEP, NF1, IGNORE)	/* FST_SPI_CLK */
+		PAD_CFG_NF_IOSSTATE(FST_SPI_CLK_FB, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CLK_FB */
+		PAD_CFG_NF_IOSSTATE(GPIO_106, NATIVE, DEEP, NF3, IGNORE)	/* FST_SPI_CS2_N */
+
+		/* SIO_SPI_0 - Used for FP */
+		PAD_CFG_NF(GPIO_104, NATIVE, DEEP, NF1)			/* SIO_SPI_0_CLK */
+		PAD_CFG_NF(GPIO_105, NATIVE, DEEP, NF1)			/* SIO_SPI_0_FS0 */
+		PAD_CFG_NF(GPIO_109, NATIVE, DEEP, NF1)			/* SIO_SPI_0_RXD */
+		PAD_CFG_NF(GPIO_110, NATIVE, DEEP, NF1)			/* SIO_SPI_0_TXD */
+
+		/* SIO_SPI_1 -- largely unused */
+		PAD_CFG_GPI(GPIO_111, UP_20K, DEEP)	 /* SIO_SPI_1_CLK */
+		PAD_CFG_GPI(GPIO_112, UP_20K, DEEP)	 /* SIO_SPI_1_FS0 */
+		PAD_CFG_GPI(GPIO_113, UP_20K, DEEP)	 /* SIO_SPI_1_FS1 */
+		/* Headset interrupt */
+		PAD_CFG_GPI_APIC_LOW(GPIO_116, NONE, DEEP) /* SIO_SPI_1_RXD */
+		PAD_CFG_GPI(GPIO_117, UP_20K, DEEP)	 /* SIO_SPI_1_TXD */
+
+		/* SIO_SPI_2 -- unused */
+		PAD_CFG_GPI(GPIO_118, UP_20K, DEEP)	 /* SIO_SPI_2_CLK */
+		PAD_CFG_GPI(GPIO_119, UP_20K, DEEP)	 /* SIO_SPI_2_FS0 */
+		PAD_CFG_GPI(GPIO_120, UP_20K, DEEP)	 /* SIO_SPI_2_FS1 */
+		PAD_CFG_GPI(GPIO_121, UP_20K, DEEP)	 /* SIO_SPI_2_FS2 */
+		/* WLAN_PE_RST - default to deasserted */
+		PAD_CFG_GPO(GPIO_122, 0, DEEP)		 /* SIO_SPI_2_RXD */
+		PAD_CFG_GPI(GPIO_123, UP_20K, DEEP)	 /* SIO_SPI_2_TXD */
+
+		/* Debug tracing */
+		PAD_CFG_GPI(GPIO_0, UP_20K, DEEP)
+		PAD_CFG_GPI(GPIO_1, UP_20K, DEEP)
+		PAD_CFG_GPI(GPIO_2, UP_20K, DEEP)
+		PAD_CFG_GPI_SCI_HIGH(GPIO_3, DN_20K, DEEP, LEVEL)	 /* FP_INT */
+		PAD_CFG_GPI(GPIO_4, UP_20K, DEEP)
+		PAD_CFG_GPI(GPIO_5, UP_20K, DEEP)
+		PAD_CFG_GPI(GPIO_6, UP_20K, DEEP)
+		PAD_CFG_GPI(GPIO_7, UP_20K, DEEP)
+		PAD_CFG_GPI(GPIO_8, UP_20K, DEEP)
+
+		PAD_CFG_GPI_APIC_LOW(GPIO_9, NONE, DEEP) /* dTPM IRQ */
+		PAD_CFG_GPI(GPIO_10, DN_20K, DEEP)	 /* Board phase enforcement */
+		PAD_CFG_GPI_SCI_LOW(GPIO_11, NONE, DEEP, EDGE_SINGLE) /* EC SCI  */
+		PAD_CFG_GPI(GPIO_12, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI_APIC_LOW(GPIO_13, NONE, DEEP) /* PEN_INT_ODL */
+		PAD_CFG_GPI_APIC_HIGH(GPIO_14, DN_20K, DEEP) /* FP_INT */
+		PAD_CFG_GPI_SCI_LOW(GPIO_15, NONE, DEEP, EDGE_SINGLE)	 /* TRACKPAD_INT_1V8_ODL */
+		PAD_CFG_GPI(GPIO_16, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_17, UP_20K, DEEP)	 /* 1 vs 4 DMIC config */
+		PAD_CFG_GPI_APIC_LOW(GPIO_18, NONE, DEEP) /* Trackpad IRQ */
+		PAD_CFG_GPI(GPIO_19, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI_APIC_LOW(GPIO_20, UP_20K, DEEP) /* NFC IRQ */
+		PAD_CFG_GPI_APIC_LOW(GPIO_21, NONE, DEEP) /* Touch IRQ */
+		PAD_CFG_GPI_SCI_LOW(GPIO_22, NONE, DEEP, EDGE_SINGLE) /* EC wake */
+		PAD_CFG_GPI(GPIO_23, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_24, NONE, DEEP)	 /* PEN_PDCT_ODL */
+		PAD_CFG_GPI(GPIO_25, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_26, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI(GPIO_27, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPI_APIC_LOW(GPIO_28, NONE, DEEP) /* TPM IRQ */
+		PAD_CFG_GPO(GPIO_29, 1, DEEP)		 /* FP reset */
+		PAD_CFG_GPI_APIC_LOW(GPIO_30, NONE, DEEP) /* KB IRQ */
+		PAD_CFG_GPO(GPIO_31, 0, DEEP)		 /* NFC FW DL */
+		PAD_CFG_NF(GPIO_32, NONE, DEEP, NF5)	 /* SUS_CLK2 */
+		PAD_CFG_GPI_APIC_LOW(GPIO_33, NONE, DEEP) /* PMIC IRQ */
+		PAD_CFG_GPI(GPIO_34, UP_20K, DEEP)	 /* unused */
+		PAD_CFG_GPO(GPIO_35, 0, DEEP)		 /* PEN_RESET - active high */
+		PAD_CFG_GPO(GPIO_36, 0, DEEP)		 /* touch reset */
+		PAD_CFG_GPI(GPIO_37, UP_20K, DEEP)	 /* unused */
+
+		/* LPSS_UART[0:2] */
+		PAD_CFG_GPI(GPIO_38, NONE, DEEP)	 /* LPSS_UART0_RXD - MEM_CONFIG2*/
+		/* Next 2 are straps */
+		PAD_CFG_GPI(GPIO_39, DN_20K, DEEP)	 /* LPSS_UART0_TXD - unused */
+		PAD_CFG_GPI(GPIO_40, DN_20K, DEEP)	 /* LPSS_UART0_RTS - unused */
+		PAD_CFG_GPI(GPIO_41, NONE, DEEP)	 /* LPSS_UART0_CTS - EC_IN_RW */
+		PAD_CFG_NF(GPIO_42, NATIVE, DEEP, NF1)	 /* LPSS_UART1_RXD */
+		PAD_CFG_NF(GPIO_43, NATIVE, DEEP, NF1)	 /* LPSS_UART1_TXD */
+		PAD_CFG_GPO(GPIO_44, 1, DEEP)	 /* GPS_RST_ODL */
+		PAD_CFG_GPI(GPIO_45, NONE, DEEP)	 /* LPSS_UART1_CTS - MEM_CONFIG3 */
+		PAD_CFG_NF(GPIO_46, NATIVE, DEEP, NF1)	 /* LPSS_UART2_RXD */
+		PAD_CFG_NF_IOSSTATE(GPIO_47, NATIVE, DEEP, NF1, TX1_RX_DCR_X0) /* UART2 TX */
+		PAD_CFG_GPI(GPIO_48, UP_20K, DEEP)	 /* LPSS_UART2_RTS - unused */
+		PAD_CFG_GPI_SMI_LOW(GPIO_49, NONE, DEEP, EDGE_SINGLE) /* LPSS_UART2_CTS - EC_SMI_L */
+
+		/* Camera interface -- completely unused */
+		PAD_CFG_GPI(GPIO_62, UP_20K, DEEP)	 /* GP_CAMERASB00 */
+		PAD_CFG_GPI(GPIO_63, UP_20K, DEEP)	 /* GP_CAMERASB01 */
+		PAD_CFG_GPI(GPIO_64, UP_20K, DEEP)	 /* GP_CAMERASB02 */
+		PAD_CFG_GPI(GPIO_65, UP_20K, DEEP)	 /* GP_CAMERASB03 */
+		PAD_CFG_GPI(GPIO_66, UP_20K, DEEP)	 /* GP_CAMERASB04 */
+		PAD_CFG_GPI(GPIO_67, UP_20K, DEEP)	 /* GP_CAMERASB05 */
+		PAD_CFG_GPI(GPIO_68, UP_20K, DEEP)	 /* GP_CAMERASB06 */
+		PAD_CFG_GPI(GPIO_69, UP_20K, DEEP)	 /* GP_CAMERASB07 */
+		PAD_CFG_GPI(GPIO_70, UP_20K, DEEP)	 /* GP_CAMERASB08 */
+		PAD_CFG_GPI(GPIO_71, UP_20K, DEEP)	 /* GP_CAMERASB09 */
+		PAD_CFG_GPI(GPIO_72, UP_20K, DEEP)	 /* GP_CAMERASB10 */
+		PAD_CFG_GPI(GPIO_73, UP_20K, DEEP)	 /* GP_CAMERASB11 */
+	>;
+};
diff --git a/board/google/Kconfig b/board/google/Kconfig
index 679a0f10239..1d67fda0676 100644
--- a/board/google/Kconfig
+++ b/board/google/Kconfig
@@ -60,8 +60,23 @@ config TARGET_CHROMEBOOK_SAMUS_TPL
 	  between different A/B versions of SPL/U-Boot, to allow upgrading of
 	  almost all U-Boot code in the field.
 
+config TARGET_CHROMEBOOK_CORAL
+	bool "Chromebook coral"
+	help
+	  This is a range of Intel-based laptops released in 2018. They use an
+	  Intel Apollolake CPU. The design supports WiFi, 4GB to 16GB of
+	  LPDDR4 1600MHz SDRAM, PCIe WiFi and Bluetooth, eMMC (typically 32GB),
+	  up two cameras (front-facing 720p and another 5MP option), USB SD
+	  reader, microphone and speakers. It also includes two USB 3 Type A and
+	  two Type C ports. The latter are used as power input and can also
+	  charge external devices as well as a 4K external display. There is a
+	  Chrome OS EC connected on LPC, a Cr50 secure chip from Google and
+	  various display options. OEMs products include Acer Chromebook 11
+	  (e.g. C732, CB11, CP311) and Lenovo Chromebook (100e, 300e, 500e).
+
 endchoice
 
+source "board/google/chromebook_coral/Kconfig"
 source "board/google/chromebook_link/Kconfig"
 source "board/google/chromebox_panther/Kconfig"
 source "board/google/chromebook_samus/Kconfig"
diff --git a/board/google/chromebook_coral/Kconfig b/board/google/chromebook_coral/Kconfig
new file mode 100644
index 00000000000..940bee89b0b
--- /dev/null
+++ b/board/google/chromebook_coral/Kconfig
@@ -0,0 +1,43 @@
+if TARGET_CHROMEBOOK_CORAL
+
+config SYS_BOARD
+	default "chromebook_coral"
+
+config SYS_VENDOR
+	default "google"
+
+config SYS_SOC
+	default "apollolake"
+
+config SYS_CONFIG_NAME
+	default "chromebook_coral"
+
+config SYS_TEXT_BASE
+	default 0xffe00000
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select X86_RESET_VECTOR
+	select INTEL_APOLLOLAKE
+	select BOARD_ROMSIZE_KB_16384
+
+config PCIE_ECAM_BASE
+	default 0xf0000000
+
+config EARLY_POST_CROS_EC
+	bool "Enable early post to Chrome OS EC"
+	help
+	  Allow post codes to be sent to the Chroem OS EC early during boot,
+	  to enable monitoring of the boot and debugging when things go wrong.
+	  With this option enabled, the EC console can be used to watch post
+	  codes the first part of boot.
+
+config SYS_CAR_ADDR
+	hex
+	default 0xfef00000
+
+config SYS_CAR_SIZE
+	hex
+	default 0xc0000
+
+endif
diff --git a/board/google/chromebook_coral/MAINTAINERS b/board/google/chromebook_coral/MAINTAINERS
new file mode 100644
index 00000000000..904227e2e21
--- /dev/null
+++ b/board/google/chromebook_coral/MAINTAINERS
@@ -0,0 +1,6 @@
+CHROMEBOOK_CORAL_BOARD
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/google/chromebook_coral/
+F:	include/configs/chromebook_coral.h
+F:	configs/chromebook_coral_defconfig
diff --git a/board/google/chromebook_coral/Makefile b/board/google/chromebook_coral/Makefile
new file mode 100644
index 00000000000..6a27ce3da1b
--- /dev/null
+++ b/board/google/chromebook_coral/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2019 Google LLC
+
+obj-y	+= coral.o
diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c
new file mode 100644
index 00000000000..dfe0fa484a1
--- /dev/null
+++ b/board/google/chromebook_coral/coral.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+
+int arch_misc_init(void)
+{
+	return 0;
+}
+
+int board_run_command(const char *cmdline)
+{
+	printf("No command line\n");
+
+	return 0;
+}
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
new file mode 100644
index 00000000000..6b586ef3c77
--- /dev/null
+++ b/configs/chromebook_coral_defconfig
@@ -0,0 +1,101 @@
+CONFIG_X86=y
+CONFIG_SYS_TEXT_BASE=0x1110000
+CONFIG_SYS_MALLOC_F_LEN=0x3d00
+CONFIG_SPL_SYS_MALLOC_F_LEN=0xf000
+CONFIG_NR_DRAM_BANKS=8
+CONFIG_BOOTSTAGE_STASH_ADDR=0xfef00000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xde000000
+CONFIG_DEBUG_UART_CLOCK=1843200
+CONFIG_VENDOR_GOOGLE=y
+CONFIG_TARGET_CHROMEBOOK_CORAL=y
+CONFIG_DEBUG_UART=y
+CONFIG_FSP_VERSION2=y
+CONFIG_HAVE_ACPI_RESUME=y
+CONFIG_INTEL_CAR_CQOS=y
+CONFIG_X86_OFFSET_U_BOOT=0xffe00000
+CONFIG_X86_OFFSET_SPL=0xffe80000
+CONFIG_SPL_TEXT_BASE=0xfef10000
+CONFIG_BOOTSTAGE=y
+CONFIG_SPL_BOOTSTAGE=y
+CONFIG_TPL_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=10
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_SPL_LOG=y
+CONFIG_LOG_DEFAULT_LEVEL=7
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_LAST_STAGE_INIT=y
+CONFIG_BLOBLIST=y
+# CONFIG_TPL_BLOBLIST is not set
+CONFIG_BLOBLIST_ADDR=0x100000
+CONFIG_HANDOFF=y
+CONFIG_TPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_PCI=y
+# CONFIG_SPL_SPI_FLASH_TINY is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_PMC=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_SATA=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_MAC_PARTITION=y
+# CONFIG_SPL_MAC_PARTITION is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_ISO_PARTITION=y
+CONFIG_EFI_PARTITION=y
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="chromebook_coral"
+# CONFIG_NET is not set
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_CPU=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_TPL_MISC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_SPI_FLASH_INTEL_FAST=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_X86_PCH7 is not set
+# CONFIG_X86_PCH9 is not set
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_SOUND=y
+CONFIG_SOUND_I8254=y
+CONFIG_SOUND_RT5677=y
+CONFIG_SPI=y
+CONFIG_ICH_SPI=y
+CONFIG_TPL_SYSRESET=y
+CONFIG_X86_TSC_ZERO_BASE=y
+CONFIG_TPM_TIS_LPC=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_SPL_FS_CBFS=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_TPL_USE_TINY_PRINTF=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_TPM=y
+# CONFIG_EFI_LOADER is not set
diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst
new file mode 100644
index 00000000000..c583ac2b27d
--- /dev/null
+++ b/doc/board/google/chromebook_coral.rst
@@ -0,0 +1,238 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
+
+Chromebook Coral
+================
+
+Coral is a Chromebook (or really about 20 different Chromebooks) which use the
+Intel Apollolake platform (APL). The 'reef' Chromebooks use the same APL SoC so
+should also work. Some later ones based on Glacier Lake (GLK) need various
+changes in GPIOs, etc. but are very similar.
+
+It is hoped that this port can enable ports to embedded APL boards which are
+starting to appear.
+
+Note that booting U-Boot on APL is already supported by coreboot and
+Slim Bootloader. This documentation refers to a 'bare metal' port.
+
+
+Boot flow - TPL
+---------------
+
+Apollolake boots via an IFWI (Integrated Firmware Image). TPL is placed in this,
+in the IBBL entry.
+
+On boot, an on-chip microcontroller called the CSE (Converged Security Engine)
+sets up some SDRAM at ffff8000 and loads the TPL image to that address. The
+SRAM extends up to the top of 32-bit address space, but the last 2KB is the
+start16 region, so the TPL image must be 30KB at most, and CONFIG_TPL_TEXT_BASE
+must be ffff8000. Actually the start16 region is small and it could probably
+move from f800 to fe00, providing another 1.5KB, but TPL is only about 19KB so
+there is no need to change it at present. The size limit is enforced by
+CONFIG_TPL_SIZE_LIMIT to avoid producing images that won't boot.
+
+TPL (running from start.S) first sets up CAR (Cache-as-RAM) which provides
+larger area of RAM for use while booting. CAR is mapped at CONFIG_SYS_CAR_ADDR
+(fef00000) and is 768KB in size. It then sets up the stack in the botttom 64KB
+of this space (i.e. below fef10000). This means that the stack and early
+malloc() region in TPL can be 64KB at most.
+
+TPL operates without CONFIG_TPL_PCI enabled so PCI config access must use the
+x86-specific functions pci_x86_write_config(), etc. SPL creates a simple-bus
+device so that PCI devices are bound by driver model. Then arch_cpu_init_tpl()
+is called to early init on various devices. This includes placing PCI devices
+at hard-coded addresses in the memory map. PCI auto-config is not used.
+
+Most of the 16KB ROM is mapped into the very top of memory, except for the
+Intel descriptor (first 4KB) and the space for SRAM as above.
+
+TPL does not set up a bloblist since at present it does not have anything to
+pass to SPL.
+
+Once TPL is done it loads SPL from ROM using either the memory-mapped SPI or by
+using the Intel fast SPI driver. SPL is loaded into CAR, at the address given
+by CONFIG_SPL_TEXT_BASE, which is normally fef10000.
+
+Note that booting using the SPI driver results in an TPL image that is about
+26KB in size instead of 19KB. Also boot speed is worse by about 340ms. If you
+really want to use the driver, enable CONFIG_APL_SPI_FLASH_BOOT and set
+BOOT_FROM_FAST_SPI_FLASH to true[2].
+
+
+Boot flow - SPL
+---------------
+
+SPL (running from start_from_tpl.S) continues to use the same stack as TPL.
+It calls arch_cpu_init_spl() to set up a few devices, then init_dram() loads
+the FSP-M binary into CAR and runs to, to set up SDRAM. The address of the
+output 'HOB' list (Hand-off-block) is stored into gd->arch.hob_list for parsing.
+There is a 2GB chunk of SDRAM starting at 0 and the rest is at 4GB.
+
+PCI auto-config is not used in SPL either, but CONFIG_SPL_PCI is defined, so
+proper PCI access is available and normal dm_pci_read_config() calls can be
+used. However PCI auto-config is not used so the same static memory mapping set
+up by TPL is still active.
+
+SPL on x86 always runs with CONFIG_SPL_SEPARATE_BSS=y and BSS is at 120000
+(see u-boot-spl.lds). This works because SPL doesn't access BSS until after
+board_init_r(), as per the rules, and DRAM is available then.
+
+SPL sets up a bloblist and passes the SPL hand-off information to U-Boot proper.
+This includes a pointer to the HOB list as well as DRAM information. See
+struct arch_spl_handoff. The bloblist address is set by CONFIG_BLOBLIST_ADDR,
+normally 100000.
+
+SPL uses SPI flash to update the MRC caches in ROM. This speeds up subsequent
+boots. Be warned that SPL can take 30 seconds without this cache! This is a
+known issue with Intel SoCs with modern DRAM and apparently cannot be improved.
+The MRC caches are used to work around this.
+
+Once SPL is finished it loads U-Boot into SDRAM at CONFIG_SYS_TEXT_BASE, which
+is normally 1110000. Note that CAR is still active.
+
+
+Boot flow - U-Boot pre-relocation
+---------------------------------
+
+U-Boot (running from start_from_spl.S) starts running in RAM and uses the same
+stack as SPL. It does various init activities before relocation. Notably
+arch_cpu_init_dm() sets up the pin muxing for the chip using a very large table
+in the device tree.
+
+PCI auto-config is not used before relocation, but CONFIG_PCI of course is
+defined, so proper PCI access is available. The same static memory mapping set
+up by TPL is still active until relocation.
+
+As per usual, U-Boot allocates memory at the top of available RAM (a bit below
+2GB in this case) and copies things there ready to relocate itself. Notably
+reserve_arch() does not reserve space for the HOB list returned by FSP-M since
+this is already located in RAM.
+
+U-Boot then shuts down CAR and jumps to its relocated version.
+
+
+Boot flow - U-Boot post-relocation
+---------------------------------
+
+U-Boot starts up normally, running near the top of RAM. After driver model is
+running, arch_fsp_init_r() is called which loads and runs the FSP-S binary.
+This updates the HOB list to include graphics information, used by the fsp_video
+driver.
+
+PCI autoconfig is done and a few devices are probed to complete init. Most
+others are started only when they are used.
+
+Note that FSP-S is supposed to run after CAR has been shut down, which happens
+immediately before U-Boot starts up in its relocated position. Therefore we
+cannot run FSP-S before relocation. On the other hand we must run it before
+PCI auto-config is done, since FSP-S may show or hide devices. The first device
+that probes PCI after relocation is the serial port, in initr_serial(), so FSP-S
+must run before that. A corollary is that loading FSP-S must be done without
+using the SPI driver, to avoid probing PCI and causing an autoconfig, so
+memory-mapped reading is always used for FSP-S.
+
+It would be possible to tear down CAR in SPL instead of U-Boot. The SPL handoff
+information could make sure it does not include any pointers into CAR (in fact
+it doesn't). But tearing down CAR in U-Boot allows the initial state used by TPL
+and SPL to be read by U-Boot, which seems useful. It also matches how older
+platforms start up (those that don't use SPL).
+
+
+Performance
+-----------
+
+Bootstage is used through all phases of U-Boot to keep accurate timimgs for
+boot. Use 'bootstage report' in U-Boot to see the report, e.g.:
+
+Timer summary in microseconds (16 records):
+       Mark    Elapsed  Stage
+          0          0  reset
+    155,325    155,325  TPL
+    204,014     48,689  end TPL
+    204,385        371  SPL
+    738,633    534,248  end SPL
+    739,161        528  board_init_f
+    842,764    103,603  board_init_r
+  1,166,233    323,469  main_loop
+  1,166,283         50  id=175
+
+Accumulated time:
+                    62  fast_spi
+                   202  dm_r
+                 7,779  dm_spl
+                15,555  dm_f
+               208,357  fsp-m
+               239,847  fsp-s
+               292,143  mmap_spi
+
+CPU performance is about 3500 DMIPS:
+
+=> dhry
+1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS
+
+
+Partial memory map
+------------------
+
+fefc0000        Top of CAR region
+fef96000	Stack for FSP-M
+fef40000 59000	FSP-M
+fef10000	SPL loaded here
+fef10000	Stack top in TPL, SPL and U-Boot before relocation
+fef00000  1000	CONFIG_BOOTSTAGE_STASH_ADDR
+fef00000        Base of CAR region
+
+   f0000	CONFIG_ROM_TABLE_ADDR
+  100000	CONFIG_BLOBLIST_ADDR
+  120000	BSS (defined in u-boot-spl.lds)
+  200000	FSP-S (which is run after U-Boot is relocated)
+ 1110000	CONFIG_SYS_TEXT_BASE
+
+
+Supported peripherals
+---------------------
+
+- UART
+- SPI flash
+- Video
+- MMC (dev 0) and micro-SD (dev 1)
+- Chrome OS EC
+- Keyboard
+- USB
+
+
+To do
+-----
+
+- Finish peripherals
+   - left-side USB
+   - USB-C
+   - Cr50 (security chip: a basic driver is running but not included here)
+   - I2C (driver exists but not enabled in device tree)
+   - Sound (Intel I2S support exists, but need da7219 driver)
+   - RTC (driver exists but not enabled in device tree)
+   - Various minor features supported by LPC, etc.
+- Booting Chrome OS, e.g. with verified boot
+- Integrate with Chrome OS vboot
+- Improvements to booting from coreboot (i.e. as a coreboot target)
+- Use FSP-T binary instead of our own CAR implementation
+- Use the official FSP package instead of the coreboot one
+- Enable all CPU cores
+- Suspend / resume
+- ACPI
+
+
+Credits
+-------
+
+This is a spare-time project conducted slowly over a long period of time.
+
+Much of the code for this port came from Coreboot, an open-source firmware
+project similar to U-Boot's SPL in terms of features.
+
+Also see [2] for information about the boot flow used by coreboot. It is
+similar, but has an extra postcar stage. U-Boot doesn't need this since it
+supports relocating itself in memory.
+
+
+[2] Intel PDF https://www.coreboot.org/images/2/23/Apollolake_SoC.pdf
diff --git a/drivers/i2c/dw_i2c_pci.c b/drivers/i2c/dw_i2c_pci.c
index d6d93f08a56..34cdc7bf59c 100644
--- a/drivers/i2c/dw_i2c_pci.c
+++ b/drivers/i2c/dw_i2c_pci.c
@@ -24,7 +24,7 @@ static struct dw_scl_sda_cfg byt_config = {
 };
 
 /* Have a weak function for now - possibly should be a new uclass */
-void lpss_reset_release(void *regs);
+__weak void lpss_reset_release(void *regs);
 
 static int designware_i2c_pci_probe(struct udevice *dev)
 {
diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h
new file mode 100644
index 00000000000..b5603e09ef2
--- /dev/null
+++ b/include/configs/chromebook_coral.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+/*
+ * board/config.h - configuration options, board-specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_BOOTCOMMAND
+
+#include <configs/x86-common.h>
+#include <configs/x86-chromebook.h>
+
+#undef CONFIG_STD_DEVICES_SETTINGS
+#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,i8042-kbd,serial\0" \
+					"stdout=vidconsole,serial\0" \
+					"stderr=vidconsole,serial\0"
+
+#define CONFIG_ENV_SECT_SIZE		0x1000
+#define CONFIG_ENV_OFFSET		0x003f8000
+
+#define CONFIG_TPL_TEXT_BASE		0xffff8000
+
+#define CONFIG_SYS_NS16550_MEM32
+#undef CONFIG_SYS_NS16550_PORT_MAPPED
+
+#endif	/* __CONFIG_H */
-- 
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver Simon Glass
@ 2019-10-21  7:46   ` Andy Shevchenko
  2019-10-21 22:53     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  7:46 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:28 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add a driver for the apollolake UART. It uses the standard ns16550 device
> but also sets up the input clock with LPSS and supports configuration via
> of-platdata.

This must be generic driver. The LPSS block is the same for all Intel
SoCs starting from Skylake.
Making it generic will reduce double efforts in the future.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command Simon Glass
@ 2019-10-21  7:48   ` Andy Shevchenko
  2019-10-21 22:53     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  7:48 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:26 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add a simple command to show information about the PMC.

PMC is a part of almost all Intel Atom SoCs. Can you describe how can
it be utilized for example in case of Tangier?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus Simon Glass
@ 2019-10-21  7:52   ` Andy Shevchenko
  2019-10-21 22:53     ` Simon Glass
  2019-10-28  7:12   ` Bin Meng
  1 sibling, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  7:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:24 AM Simon Glass <sjg@chromium.org> wrote:
>
> In TPL we try to minimise code size so do not include the PCI subsystem.
> We can use fixed BARs and drivers can directly program the devices that
> they need.
>
> However we do need to bind the devices on the PCI bus and without PCI this
> does not ordinarily happen. As a work-around, define a fake PCI bus which
> does this binding, but no other PCI operations. This is a convenient way
> to ensure that we can use the same device tree for TPL, SPL and U-Boot
> proper:
>
>    TPL    - CONFIG_TPL_PCI is not set (no auto-config, fake PCI bus)
>    SPL    - CONFIG_SPL_PCI is set (no auto-config but with real PCI bus)
>    U-Boot - CONFIG_PCI is set (full auto-config after relocation)

PCI(e) bus is present in a lot of SoCs (not exclusively x86). Perhaps
better idea is to have something like lib/pci.c with minimum support
for PCI type 1 and probably PCI type 2 accessors and other very basic
functions.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 093/108] x86: apollolake: Add GPIO driver
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 093/108] x86: apollolake: Add GPIO driver Simon Glass
@ 2019-10-21  7:57   ` Andy Shevchenko
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  7:57 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:02 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add a driver for the apollolake GPIOs. It also handles pinctrl since this
> is not very well separated on x86.

>  arch/x86/cpu/apollolake/gpio.c                | 735 ++++++++++++++++++

No, no. It must be a common for x86, starting from Skylake.
See how it's done in Linux kernel.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes Simon Glass
@ 2019-10-21  8:11   ` Andy Shevchenko
  2019-11-19  8:02   ` Bin Meng
  1 sibling, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:11 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:01 AM Simon Glass <sjg@chromium.org> wrote:
>
> Newer Intel SoCs have different ways of setting up cache-as-ram (CAR).
> Add support for these along with suitable configuration options.


> +#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)

Perhaps it would be useful to have a generic macro

#define CONFIG_VALUE_IS_POWER_OF_2(_x)   (CONFIG_##_x ...)

> +#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */

> +#else
> +#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
> +#endif


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 091/108] x86: apollolake: Add low-power subsystem (lpss) support
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 091/108] x86: apollolake: Add low-power subsystem (lpss) support Simon Glass
@ 2019-10-21  8:14   ` Andy Shevchenko
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:14 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 6:53 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add very basic support for taking an lpss device out of reset.

>  arch/x86/cpu/apollolake/lpss.c   | 31 +++++++++++++++++++++++++++++++

Must be in intel_common.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 095/108] x86: apollolake: Add systemagent driver
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 095/108] x86: apollolake: Add systemagent driver Simon Glass
@ 2019-10-21  8:16   ` Andy Shevchenko
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:16 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:29 AM Simon Glass <sjg@chromium.org> wrote:
>
> This driver handles communication with the systemagent which needs to be
> told when U-Boot has completed its init.

> +#define VTBAR_MASK             0xfffffff000ull

Don't we have GENMASK() ?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver Simon Glass
@ 2019-10-21  8:41   ` Andy Shevchenko
  2019-10-21  8:43     ` Andy Shevchenko
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:41 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 6:58 AM Simon Glass <sjg@chromium.org> wrote:
>
> This driver models some sort of interrupt thingy but there are so many
> abreviations that I cannot find out what it stands for. Possibly something
> to do with interrupts.

From documentation.
Interrupt Timer Subsystem

The below code is only small part of what it can do / does.

>  arch/x86/cpu/apollolake/itss.c              | 214 ++++++++++++++++++++

P.S. Heard first time today about it.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-21  8:41   ` Andy Shevchenko
@ 2019-10-21  8:43     ` Andy Shevchenko
  2019-10-21 22:53       ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:43 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:41 AM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 6:58 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > This driver models some sort of interrupt thingy but there are so many
> > abreviations that I cannot find out what it stands for. Possibly something
> > to do with interrupts.
>
> From documentation.
> Interrupt Timer Subsystem
>
> The below code is only small part of what it can do / does.
>
> >  arch/x86/cpu/apollolake/itss.c              | 214 ++++++++++++++++++++
>
> P.S. Heard first time today about it.

Okay, nailed it. It's a re-make of iLB. So, basically this has to be a
part of iLB driver(s).

In BXT it contains legacy (8254, 8259) and standard (HPET, IOAPIC) devices.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 100/108] x86: apollolake: Add PUNIT driver
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 100/108] x86: apollolake: Add PUNIT driver Simon Glass
@ 2019-10-21  8:47   ` Andy Shevchenko
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:47 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:25 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add a driver for the apollolake power unit. It is modelled as a syscon
> driver since it only needs to be probed.

appollolake -> Appollo Lake (everywhere in the series)
power unit -> P-Unit (it's very known for Intel SoCs term, you may
decode it as well, but use this known semi-abbreviation)
modelled -> modeled


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver Simon Glass
@ 2019-10-21  8:49   ` Andy Shevchenko
  2019-10-21 22:53     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-21  8:49 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 7:14 AM Simon Glass <sjg@chromium.org> wrote:
>
> Adds a driver for the apollolake Primary-to-sideband bus. This supports
> various child devices. It supposed both device tree and of-platdata.

> +static int apl_p2sb_probe(struct udevice *dev)
> +{
> +       if (spl_phase() == PHASE_TPL)
> +               return apl_p2sb_early_init(dev);

> +       else if (spl_phase() == PHASE_SPL)

Redundant 'else' (recommended to check for a such in the entire series)

> +               return apl_p2sb_spl_init(dev);
> +
> +       return 0;
> +}

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (85 preceding siblings ...)
  2019-10-21  3:39 ` [U-Boot] [PATCH v3 108/108] x86: Add chromebook_coral Simon Glass
@ 2019-10-21 19:15 ` Park, Aiden
  2019-10-28  7:12 ` Bin Meng
  87 siblings, 0 replies; 201+ messages in thread
From: Park, Aiden @ 2019-10-21 19:15 UTC (permalink / raw)
  To: u-boot

> -----Original Message-----
> From: Simon Glass [mailto:sjg at chromium.org]
> Sent: Sunday, October 20, 2019 8:38 PM
> To: U-Boot Mailing List <u-boot@lists.denx.de>
> Cc: Bin Meng <bmeng.cn@gmail.com>; Simon Glass <sjg@chromium.org>;
> Andy Shevchenko <andy.shevchenko@gmail.com>; Bernhard Messerklinger
> <bernhard.messerklinger@br-automation.com>; Park, Aiden
> <aiden.park@intel.com>; Simon Goldschmidt
> <simon.k.r.goldschmidt@gmail.com>; Stefan Roese <sr@denx.de>
> Subject: [PATCH v3 022/108] x86: timer: Use a separate flag for whether
> timer is inited
> 
> At present the value of the timer base is used to determine whether the
> timer has been set up or not. It is true that the timer is essentially never
> exactly 0 when it is read. However 'time 0' may indicate the time that the
> machine was reset so it is useful to be able to denote that.
> 
> Update the code to use a separate flag instead.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>  arch/x86/include/asm/global_data.h | 1 +
>  drivers/timer/tsc_timer.c          | 3 ++-
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/include/asm/global_data.h
> b/arch/x86/include/asm/global_data.h
> index 17a4d344913..7f3ada06f61 100644
> --- a/arch/x86/include/asm/global_data.h
> +++ b/arch/x86/include/asm/global_data.h
> @@ -76,6 +76,7 @@ struct arch_global_data {
>  	uint8_t x86_mask;
>  	uint32_t x86_device;
>  	uint64_t tsc_base;		/* Initial value returned by rdtsc() */
> +	bool tsc_inited;		/* true if tsc is ready for use */
>  	unsigned long clock_rate;	/* Clock rate of timer in Hz */
>  	void *new_fdt;			/* Relocated FDT */
>  	uint32_t bist;			/* Built-in self test value */
> diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index
> f19d2237e4f..637c8ff25a5 100644
> --- a/drivers/timer/tsc_timer.c
> +++ b/drivers/timer/tsc_timer.c
> @@ -394,7 +394,7 @@ static int tsc_timer_get_count(struct udevice *dev,
> u64 *count)
> 
>  static void tsc_timer_ensure_setup(bool early)  {
> -	if (gd->arch.tsc_base)
> +	if (gd->arch.tsc_inited)
>  		return;
>  	gd->arch.tsc_base = rdtsc();
> 
> @@ -425,6 +425,7 @@ static void tsc_timer_ensure_setup(bool early)
>  done:
>  		gd->arch.clock_rate = fast_calibrate * 1000000;
>  	}
> +	gd->arch.tsc_inited = true;
>  }
> 
>  static int tsc_timer_probe(struct udevice *dev)
> --
> 2.23.0.866.gb869b98d4c-goog

Verified with slimbootloader on QEMU and an APL board

Tested-by: Aiden Park <aiden.park@intel.com> 
Reviewed-by: Aiden Park <aiden.park@intel.com>

Best Regards,
Aiden

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver
  2019-10-21  7:46   ` Andy Shevchenko
@ 2019-10-21 22:53     ` Simon Glass
  2019-10-22  8:21       ` Andy Shevchenko
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21 22:53 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Mon, 21 Oct 2019 at 01:46, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 7:28 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Add a driver for the apollolake UART. It uses the standard ns16550 device
> > but also sets up the input clock with LPSS and supports configuration via
> > of-platdata.
>
> This must be generic driver. The LPSS block is the same for all Intel
> SoCs starting from Skylake.
> Making it generic will reduce double efforts in the future.

This uses ns16550.

Are you saying that lpss.c should go in intel_common? I can do that.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command
  2019-10-21  7:48   ` Andy Shevchenko
@ 2019-10-21 22:53     ` Simon Glass
  2019-10-22  8:21       ` Andy Shevchenko
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21 22:53 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Mon, 21 Oct 2019 at 01:49, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 7:26 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Add a simple command to show information about the PMC.
>
> PMC is a part of almost all Intel Atom SoCs. Can you describe how can
> it be utilized for example in case of Tangier?

Well if the driver is enabled then I expect the 'pmc info' command
could be used there?

Regards,
SImon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-21  7:52   ` Andy Shevchenko
@ 2019-10-21 22:53     ` Simon Glass
  2019-10-22  8:19       ` Andy Shevchenko
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21 22:53 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Mon, 21 Oct 2019 at 01:52, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 7:24 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > In TPL we try to minimise code size so do not include the PCI subsystem.
> > We can use fixed BARs and drivers can directly program the devices that
> > they need.
> >
> > However we do need to bind the devices on the PCI bus and without PCI this
> > does not ordinarily happen. As a work-around, define a fake PCI bus which
> > does this binding, but no other PCI operations. This is a convenient way
> > to ensure that we can use the same device tree for TPL, SPL and U-Boot
> > proper:
> >
> >    TPL    - CONFIG_TPL_PCI is not set (no auto-config, fake PCI bus)
> >    SPL    - CONFIG_SPL_PCI is set (no auto-config but with real PCI bus)
> >    U-Boot - CONFIG_PCI is set (full auto-config after relocation)
>
> PCI(e) bus is present in a lot of SoCs (not exclusively x86). Perhaps
> better idea is to have something like lib/pci.c with minimum support
> for PCI type 1 and probably PCI type 2 accessors and other very basic
> functions.

I don't know of any use case for PCI in TPL on other platforms.

x86 is I think unique in that it requires PCI to do anything. For
other platforms I am familiar with they can boot a fair way without
it.

I do want to avoid the premature-optimisation problem, i.e. inventing
new use cases that no one uses. The only thing we really know right
now is that we need this for newer x86 platforms.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-21  8:43     ` Andy Shevchenko
@ 2019-10-21 22:53       ` Simon Glass
  2019-10-22  8:22         ` Andy Shevchenko
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-21 22:53 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Mon, 21 Oct 2019 at 02:44, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:41 AM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> >
> > On Mon, Oct 21, 2019 at 6:58 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > This driver models some sort of interrupt thingy but there are so many
> > > abreviations that I cannot find out what it stands for. Possibly something
> > > to do with interrupts.
> >
> > From documentation.
> > Interrupt Timer Subsystem
> >
> > The below code is only small part of what it can do / does.
> >
> > >  arch/x86/cpu/apollolake/itss.c              | 214 ++++++++++++++++++++
> >
> > P.S. Heard first time today about it.
>
> Okay, nailed it. It's a re-make of iLB. So, basically this has to be a
> part of iLB driver(s).
>
> In BXT it contains legacy (8254, 8259) and standard (HPET, IOAPIC) devices.

OK. Where is the iLB driver? So are any changes needed for this patch?

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver
  2019-10-21  8:49   ` Andy Shevchenko
@ 2019-10-21 22:53     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-21 22:53 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Mon, 21 Oct 2019 at 02:49, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 7:14 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Adds a driver for the apollolake Primary-to-sideband bus. This supports
> > various child devices. It supposed both device tree and of-platdata.
>
> > +static int apl_p2sb_probe(struct udevice *dev)
> > +{
> > +       if (spl_phase() == PHASE_TPL)
> > +               return apl_p2sb_early_init(dev);
>
> > +       else if (spl_phase() == PHASE_SPL)
>
> Redundant 'else' (recommended to check for a such in the entire series)

This is a style thing. I like the else so that it is clear that we
have two options. I could use a switch() but then it needs to have a
'default' which is ugly.
>
> > +               return apl_p2sb_spl_init(dev);
> > +
> > +       return 0;
> > +}

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-21 22:53     ` Simon Glass
@ 2019-10-22  8:19       ` Andy Shevchenko
  2019-10-22 13:50         ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-22  8:19 UTC (permalink / raw)
  To: u-boot

On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> On Mon, 21 Oct 2019 at 01:52, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Mon, Oct 21, 2019 at 7:24 AM Simon Glass <sjg@chromium.org> wrote:

> > PCI(e) bus is present in a lot of SoCs (not exclusively x86). Perhaps
> > better idea is to have something like lib/pci.c with minimum support
> > for PCI type 1 and probably PCI type 2 accessors and other very basic
> > functions.
>
> I don't know of any use case for PCI in TPL on other platforms.
>
> x86 is I think unique in that it requires PCI to do anything.

I don't think so. PCI is a core part of the SoC, indeed, though what
exactly do we need from it here? IO accessors to PCI configuration
space?

> For
> other platforms I am familiar with they can boot a fair way without
> it.

Perhaps we may achieve the same here?

> I do want to avoid the premature-optimisation problem, i.e. inventing
> new use cases that no one uses. The only thing we really know right
> now is that we need this for newer x86 platforms.


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command
  2019-10-21 22:53     ` Simon Glass
@ 2019-10-22  8:21       ` Andy Shevchenko
  2019-10-22 13:50         ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-22  8:21 UTC (permalink / raw)
  To: u-boot

On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> On Mon, 21 Oct 2019 at 01:49, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> >
> > On Mon, Oct 21, 2019 at 7:26 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Add a simple command to show information about the PMC.
> >
> > PMC is a part of almost all Intel Atom SoCs. Can you describe how can
> > it be utilized for example in case of Tangier?
>
> Well if the driver is enabled then I expect the 'pmc info' command
> could be used there?

PMC is unique to a platform / SoC. My question here is to provide some
skeleton / Documentation how other (non-APL) SoC drivers can enable
`pmc info` etc.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver
  2019-10-21 22:53     ` Simon Glass
@ 2019-10-22  8:21       ` Andy Shevchenko
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-22  8:21 UTC (permalink / raw)
  To: u-boot

On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> On Mon, 21 Oct 2019 at 01:46, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> >
> > On Mon, Oct 21, 2019 at 7:28 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Add a driver for the apollolake UART. It uses the standard ns16550 device
> > > but also sets up the input clock with LPSS and supports configuration via
> > > of-platdata.
> >
> > This must be generic driver. The LPSS block is the same for all Intel
> > SoCs starting from Skylake.
> > Making it generic will reduce double efforts in the future.
>
> This uses ns16550.
>
> Are you saying that lpss.c should go in intel_common? I can do that.

Yes.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-21 22:53       ` Simon Glass
@ 2019-10-22  8:22         ` Andy Shevchenko
  2019-10-22 13:50           ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-22  8:22 UTC (permalink / raw)
  To: u-boot

On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> On Mon, 21 Oct 2019 at 02:44, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

> OK. Where is the iLB driver? So are any changes needed for this patch?

I guess in U-Boot we call it LPC... (What a mess with all this abbreviations!)

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command
  2019-10-22  8:21       ` Andy Shevchenko
@ 2019-10-22 13:50         ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-22 13:50 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Tue, 22 Oct 2019 at 02:21, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> > On Mon, 21 Oct 2019 at 01:49, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > >
> > > On Mon, Oct 21, 2019 at 7:26 AM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Add a simple command to show information about the PMC.
> > >
> > > PMC is a part of almost all Intel Atom SoCs. Can you describe how can
> > > it be utilized for example in case of Tangier?
> >
> > Well if the driver is enabled then I expect the 'pmc info' command
> > could be used there?
>
> PMC is unique to a platform / SoC. My question here is to provide some
> skeleton / Documentation how other (non-APL) SoC drivers can enable
> `pmc info` etc.

OK I see. I suspect that there might be some common fields but also
some fields specific to each SoC.

My expectation is that we would print out whatever of these fields
seems useful/suitable. Does that sound reasonable?

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-22  8:19       ` Andy Shevchenko
@ 2019-10-22 13:50         ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-10-22 13:50 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Tue, 22 Oct 2019 at 02:19, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> > On Mon, 21 Oct 2019 at 01:52, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Mon, Oct 21, 2019 at 7:24 AM Simon Glass <sjg@chromium.org> wrote:
>
> > > PCI(e) bus is present in a lot of SoCs (not exclusively x86). Perhaps
> > > better idea is to have something like lib/pci.c with minimum support
> > > for PCI type 1 and probably PCI type 2 accessors and other very basic
> > > functions.
> >
> > I don't know of any use case for PCI in TPL on other platforms.
> >
> > x86 is I think unique in that it requires PCI to do anything.
>
> I don't think so. PCI is a core part of the SoC, indeed, though what
> exactly do we need from it here? IO accessors to PCI configuration
> space?

I mean that on other SoCs I am familiar with you can access
peripherals through memory-mapped I/O.

On x86 so far as I am aware you can't see any peripheral without doing
some PCI config.

Therefore PCI is 'more core' on x86 than others. For example on an
Nvidia chip I am familiar with, you can do everything except enable
the PCI network chip, which you wouldn't do in TPL.

>
> > For
> > other platforms I am familiar with they can boot a fair way without
> > it.
>
> Perhaps we may achieve the same here?
>
> > I do want to avoid the premature-optimisation problem, i.e. inventing
> > new use cases that no one uses. The only thing we really know right
> > now is that we need this for newer x86 platforms.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-22  8:22         ` Andy Shevchenko
@ 2019-10-22 13:50           ` Simon Glass
  2019-10-22 18:56             ` Andy Shevchenko
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-10-22 13:50 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Tue, 22 Oct 2019 at 02:23, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> > On Mon, 21 Oct 2019 at 02:44, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> > OK. Where is the iLB driver? So are any changes needed for this patch?
>
> I guess in U-Boot we call it LPC... (What a mess with all this abbreviations!)

OK. So is this right?

LPC - Low-Pin-Count bus
iLB - Intel Legacy Block

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver
  2019-10-22 13:50           ` Simon Glass
@ 2019-10-22 18:56             ` Andy Shevchenko
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Shevchenko @ 2019-10-22 18:56 UTC (permalink / raw)
  To: u-boot

On Tue, Oct 22, 2019 at 4:51 PM Simon Glass <sjg@chromium.org> wrote:
> On Tue, 22 Oct 2019 at 02:23, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Tue, Oct 22, 2019 at 1:54 AM Simon Glass <sjg@chromium.org> wrote:
> > > On Mon, 21 Oct 2019 at 02:44, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> >
> > > OK. Where is the iLB driver? So are any changes needed for this patch?
> >
> > I guess in U-Boot we call it LPC... (What a mess with all this abbreviations!)
>
> OK. So is this right?
>
> LPC - Low-Pin-Count bus
> iLB - Intel Legacy Block

Yes.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 094/108] i2c: designware: Add apollolake support
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 094/108] i2c: designware: Add apollolake support Simon Glass
@ 2019-10-28  4:47   ` Heiko Schocher
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Schocher @ 2019-10-28  4:47 UTC (permalink / raw)
  To: u-boot

Hello Simon,

Am 21.10.2019 um 05:38 schrieb Simon Glass:
> For apollolake we need to take the I2C bus controller out of reset before
> using this. Add this functionality to the driver.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> Changes in v3:
> - Add a weak function to avoid errors on other platforms
> 
> Changes in v2: None
> 
>   drivers/i2c/dw_i2c_pci.c | 20 +++++++++++++++++++-
>   1 file changed, 19 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/dw_i2c_pci.c b/drivers/i2c/dw_i2c_pci.c
> index 065c0aa5994..d6d93f08a56 100644
> --- a/drivers/i2c/dw_i2c_pci.c
> +++ b/drivers/i2c/dw_i2c_pci.c
> @@ -6,8 +6,14 @@
>    */
>   
>   #include <dm.h>
> +#include <asm/lpss.h>
>   #include "designware_i2c.h"
>   
> +enum {
> +	VANILLA		= 0,
> +	INTEL_APL,
> +};
> +
>   /* BayTrail HCNT/LCNT/SDA hold time */
>   static struct dw_scl_sda_cfg byt_config = {
>   	.ss_hcnt = 0x200,
> @@ -17,6 +23,9 @@ static struct dw_scl_sda_cfg byt_config = {
>   	.sda_hold = 0x6,
>   };
>   
> +/* Have a weak function for now - possibly should be a new uclass */
> +void lpss_reset_release(void *regs);
> +
>   static int designware_i2c_pci_probe(struct udevice *dev)
>   {
>   	struct dw_i2c *priv = dev_get_priv(dev);
> @@ -25,9 +34,12 @@ static int designware_i2c_pci_probe(struct udevice *dev)
>   	priv->regs = (struct i2c_regs *)
>   		dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
>   	if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
> -		/* Use BayTrail specific timing values */
> +		/* Use BayTrail-specific timing values */

Nitpick only: unrelated change.

Reviewed-by: Heiko Schocher <hs@denx.de>

[...]

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs at denx.de

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited
  2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
                   ` (86 preceding siblings ...)
  2019-10-21 19:15 ` [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Park, Aiden
@ 2019-10-28  7:12 ` Bin Meng
  2019-11-02  9:47   ` Bin Meng
  87 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:12 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:39 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present the value of the timer base is used to determine whether the
> timer has been set up or not. It is true that the timer is essentially
> never exactly 0 when it is read. However 'time 0' may indicate the time
> that the machine was reset so it is useful to be able to denote that.
>
> Update the code to use a separate flag instead.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/include/asm/global_data.h | 1 +
>  drivers/timer/tsc_timer.c          | 3 ++-
>  2 files changed, 3 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT Simon Glass
@ 2019-10-28  7:12   ` Bin Meng
  2019-11-02  9:49     ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:12 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The x86 power unit handles power management. Support initing this device
> which is modelled as a new type of system controller since there are no
> operations needed.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Fix 'err-%d' typo
>
> Changes in v2: None
>
>  arch/x86/include/asm/cpu.h |  1 +
>  arch/x86/lib/spl.c         | 40 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 41 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus Simon Glass
  2019-10-21  7:52   ` Andy Shevchenko
@ 2019-10-28  7:12   ` Bin Meng
  2019-11-02  9:49     ` Bin Meng
  1 sibling, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:12 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> In TPL we try to minimise code size so do not include the PCI subsystem.
> We can use fixed BARs and drivers can directly program the devices that
> they need.
>
> However we do need to bind the devices on the PCI bus and without PCI this
> does not ordinarily happen. As a work-around, define a fake PCI bus which
> does this binding, but no other PCI operations. This is a convenient way
> to ensure that we can use the same device tree for TPL, SPL and U-Boot
> proper:
>
>    TPL    - CONFIG_TPL_PCI is not set (no auto-config, fake PCI bus)
>    SPL    - CONFIG_SPL_PCI is set (no auto-config but with real PCI bus)
>    U-Boot - CONFIG_PCI is set (full auto-config after relocation)
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Fix 'autoallocation' typo
> - Improve wording in commit message
>
> Changes in v2: None
>
>  arch/x86/lib/tpl.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs Simon Glass
@ 2019-10-28  7:26   ` Bin Meng
  2019-11-02 18:25     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:26 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Most of the timer-calibration methods are not needed on recent Intel CPUs
> and just increase code size. Add an option to use the known-good way to
> get the clock frequency in TPL. Size reduction is about 700 bytes.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/timer/Kconfig     | 9 +++++++++
>  drivers/timer/tsc_timer.c | 7 +++++--
>  2 files changed, 14 insertions(+), 2 deletions(-)
>

You mentioned in the v2 that this breaks bootstage, and will drop this
patch. no?
https://www.mail-archive.com/u-boot at lists.denx.de/msg344229.html

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 028/108] x86: Drop unnecessary interrupt code for TPL
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 028/108] x86: Drop unnecessary interrupt " Simon Glass
@ 2019-10-28  7:49   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:49 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> We don't expect an exception in TPL and don't need to print out full
> details if one happens. Add a reduced version of the code for TPL.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Can we exclude the whole file from building in TPL?

> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/cpu/i386/interrupt.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function for TPL
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function " Simon Glass
@ 2019-10-28  7:50   ` Bin Meng
  2019-11-02  9:58     ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:50 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> For TPL we only need to set up the features and identify the CPU to a
> basic level. Add a function to handle that.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/cpu/i386/cpu.c           | 8 ++++++++
>  arch/x86/include/asm/u-boot-x86.h | 9 +++++++++
>  2 files changed, 17 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init()
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init() Simon Glass
@ 2019-10-28  7:52   ` Bin Meng
  2019-11-02  9:58     ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-10-28  7:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present we call spl_init() before identifying the CPU. This is not a
> good idea - e.g. if bootstage is enabled then it will try to set up the
> timer which works better if the CPU is identified.
>
> Put explicit code at each entry pointer to identify the CPU.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/cpu/start_from_spl.S | 1 +
>  arch/x86/lib/spl.c            | 4 ++++
>  arch/x86/lib/tpl.c            | 5 +++++
>  3 files changed, 10 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 027/108] x86: Drop unnecessary cpu code for TPL
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 027/108] x86: Drop unnecessary cpu code for TPL Simon Glass
@ 2019-10-28 12:56   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-10-28 12:56 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> We don't need to know every detail about the CPU in TPL. Drop some
> superfluous functions to reduce code size. Add a simple CPU detection
> algorithm which just supports Intel and AMD, since we only support TPL
> on Intel, so far.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/cpu/cpu.c      |  4 ++++
>  arch/x86/cpu/i386/cpu.c | 41 +++++++++++++++++++++++++++++++++++++----
>  2 files changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
> index 9ee4b0294ae..4795863b33c 100644
> --- a/arch/x86/cpu/cpu.c
> +++ b/arch/x86/cpu/cpu.c
> @@ -45,6 +45,7 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +#ifndef CONFIG_TPL_BUILD
>  static const char *const x86_vendor_name[] = {
>         [X86_VENDOR_INTEL]     = "Intel",
>         [X86_VENDOR_CYRIX]     = "Cyrix",
> @@ -57,6 +58,7 @@ static const char *const x86_vendor_name[] = {
>         [X86_VENDOR_NSC]       = "NSC",
>         [X86_VENDOR_SIS]       = "SiS",
>  };
> +#endif
>
>  int __weak x86_cleanup_before_linux(void)
>  {
> @@ -113,6 +115,7 @@ int icache_status(void)
>         return 1;
>  }
>
> +#ifndef CONFIG_TPL_BUILD
>  const char *cpu_vendor_name(int vendor)
>  {
>         const char *name;
> @@ -123,6 +126,7 @@ const char *cpu_vendor_name(int vendor)
>
>         return name;
>  }
> +#endif
>
>  char *cpu_get_name(char *name)
>  {
> diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
> index 90b546e7410..5a14d42cb26 100644
> --- a/arch/x86/cpu/i386/cpu.c
> +++ b/arch/x86/cpu/i386/cpu.c
> @@ -20,6 +20,7 @@
>
>  #include <common.h>
>  #include <malloc.h>
> +#include <spl.h>
>  #include <asm/control_regs.h>
>  #include <asm/cpu.h>
>  #include <asm/mp.h>
> @@ -57,6 +58,8 @@ struct cpuinfo_x86 {
>         uint8_t x86_mask;
>  };
>
> +/* gcc 7.3 does not what to drop x86_vendors, so use #ifdef */

what => want ?

> +#ifndef CONFIG_TPL_BUILD
>  /*
>   * List of cpu vendor strings along with their normalized
>   * id values.
> @@ -77,6 +80,7 @@ static const struct {
>         { X86_VENDOR_NSC,       "Geode by NSC", },
>         { X86_VENDOR_SIS,       "SiS SiS SiS ", },
>  };
> +#endif
>
>  static void load_ds(u32 segment)
>  {
> @@ -229,6 +233,7 @@ static bool has_mtrr(void)
>         return cpuid_edx(0x00000001) & (1 << 12) ? true : false;
>  }
>
> +#ifndef CONFIG_TPL_BUILD
>  static int build_vendor_name(char *vendor_name)
>  {
>         struct cpuid_result result;
> @@ -241,14 +246,42 @@ static int build_vendor_name(char *vendor_name)
>
>         return result.eax;
>  }
> +#endif
>
>  static void identify_cpu(struct cpu_device_id *cpu)
>  {
> +       cpu->device = 0; /* fix gcc 4.4.4 warning */
> +
> +       /*
> +        * Do a quick and dirty check to save space - Intel and AMD only and
> +        * just the vendor. This is enough for most TPL code.
> +        */
> +       if (spl_phase() == PHASE_TPL) {
> +               struct cpuid_result result;
> +
> +               result = cpuid(0x00000000);
> +               switch (result.ecx >> 24) {
> +               case 'l': /* GenuineIntel */
> +                       cpu->vendor = X86_VENDOR_INTEL;
> +                       break;
> +               case 'D': /* AuthenticAMD */
> +                       cpu->vendor = X86_VENDOR_AMD;
> +                       break;
> +               default:
> +                       cpu->vendor = X86_VENDOR_ANY;
> +                       break;
> +               }
> +               if (0) /* Fix compiler warning */

Can we remove this completely?

> +                       deep_magic_nexgen_probe();
> +               return;
> +       }
> +
> +/* gcc 7.3 does not what to drop x86_vendors, so use #ifdef */

what?

> +#ifndef CONFIG_TPL_BUILD
>         char vendor_name[16];
>         int i;
>
>         vendor_name[0] = '\0'; /* Unset */
> -       cpu->device = 0; /* fix gcc 4.4.4 warning */
>
>         /* Find the id and vendor_name */
>         if (!has_cpuid()) {
> @@ -264,9 +297,8 @@ static void identify_cpu(struct cpu_device_id *cpu)
>                 /* Detect NexGen with old hypercode */
>                 else if (deep_magic_nexgen_probe())
>                         memcpy(vendor_name, "NexGenDriven", 13);
> -       }
> -       if (has_cpuid()) {
> -               int  cpuid_level;
> +       } else {
> +               int cpuid_level;
>
>                 cpuid_level = build_vendor_name(vendor_name);
>                 vendor_name[12] = '\0';
> @@ -286,6 +318,7 @@ static void identify_cpu(struct cpu_device_id *cpu)
>                         break;
>                 }
>         }
> +#endif
>  }
>
>  static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0 Simon Glass
@ 2019-10-28 13:02   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-10-28 13:02 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> On some platforms the timer is reset to 0 when the SoC is reset. Having
> this as the timer base is useful since it provides an indication of how
> long it takes before U-Boot is running.
>
> When U-Boot sets the timer base to something else, time is lost and we
> no-longer have an accurate account of the time since reset. This
> particularly affects bootstage.
>
> Add an option to leave the timer base as 0 on boot.

I think we can change the timer base as 0 for all x86 native port. And
use rdtsc() for configuration when U-Boot is used as payloads, eg:
efi, coreboot, slimbootloader, etc.

>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/timer/Kconfig     | 13 +++++++++++++
>  drivers/timer/tsc_timer.c |  3 ++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL Simon Glass
@ 2019-11-02  5:52   ` Bin Meng
  2019-11-02  9:58     ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-02  5:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> We don't need to do this and it is done (in more detail) in U-Boot proper.
> Drop this to save code space.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/lib/tpl.c | 5 -----
>  1 file changed, 5 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args()
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args() Simon Glass
@ 2019-11-02  5:52   ` Bin Meng
  2019-11-02  9:58     ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-02  5:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> We already a message indicating that U-Boot is about to jump to SPL, so
> make this one a debug() to reduce code size.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/lib/tpl.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass Simon Glass
@ 2019-11-02  5:52   ` Bin Meng
  2019-11-04  8:02   ` Bin Meng
  1 sibling, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  5:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Intel x86 SoCs have a power manager/controller which handles several
> power-related aspects of the platform. Add a uclass for this, with a few
> useful operations.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Rename power-mgr uclass to acpi-pmc
>
> Changes in v2: None
>
>  drivers/power/Kconfig                    |   2 +
>  drivers/power/acpi_pmc/Kconfig           |  25 +++
>  drivers/power/acpi_pmc/Makefile          |   5 +
>  drivers/power/acpi_pmc/acpi-pmc-uclass.c | 191 +++++++++++++++++++++++
>  include/dm/uclass-id.h                   |   1 +
>  include/power/acpi_pmc.h                 | 185 ++++++++++++++++++++++
>  6 files changed, 409 insertions(+)
>  create mode 100644 drivers/power/acpi_pmc/Kconfig
>  create mode 100644 drivers/power/acpi_pmc/Makefile
>  create mode 100644 drivers/power/acpi_pmc/acpi-pmc-uclass.c
>  create mode 100644 include/power/acpi_pmc.h
>
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index 9495dca33b9..4b4f6d55568 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -4,6 +4,8 @@ source "drivers/power/domain/Kconfig"
>
>  source "drivers/power/pmic/Kconfig"
>
> +source "drivers/power/acpi_pmc/Kconfig"

nits: this should be inserted in the alphabetical order

> +
>  source "drivers/power/regulator/Kconfig"
>
>  choice
> diff --git a/drivers/power/acpi_pmc/Kconfig b/drivers/power/acpi_pmc/Kconfig
> new file mode 100644
> index 00000000000..472a61a9fd1
> --- /dev/null
> +++ b/drivers/power/acpi_pmc/Kconfig
> @@ -0,0 +1,25 @@
> +config ACPI_PMC
> +       bool "Power Manager (x86 PMC) support"
> +       help
> +         Enable support for an x86-style power-management controller which
> +         provides features including checking whether the system started from
> +         resume, powering off the system and enabling/disabling the reset
> +         mechanism.
> +
> +config SPL_ACPI_PMC
> +       bool "Power Manager (x86 PMC) support in SPL"
> +       default y if ACPI_PMC
> +       help
> +         Enable support for an x86-style power-management controller which
> +         provides features including checking whether the system started from
> +         resume, powering off the system and enabling/disabling the reset
> +         mechanism.
> +
> +config TPL_ACPI_PMC
> +       bool "Power Manager (x86 PMC) support in TPL"
> +       default y if ACPI_PMC
> +       help
> +         Enable support for an x86-style power-management controller which
> +         provides features including checking whether the system started from
> +         resume, powering off the system and enabling/disabling the reset
> +         mechanism.
> diff --git a/drivers/power/acpi_pmc/Makefile b/drivers/power/acpi_pmc/Makefile
> new file mode 100644
> index 00000000000..7c1ba05c9f3
> --- /dev/null
> +++ b/drivers/power/acpi_pmc/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright 2019 Google LLC
> +
> +obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += acpi-pmc-uclass.o
> diff --git a/drivers/power/acpi_pmc/acpi-pmc-uclass.c b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
> new file mode 100644
> index 00000000000..8800afecf10
> --- /dev/null
> +++ b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
> @@ -0,0 +1,191 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 Google LLC
> + */
> +
> +#define LOG_CATEGORY UCLASS_ACPI_PMC
> +
> +#include <common.h>
> +#include <acpi_s3.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <asm/io.h>
> +#ifdef CONFIG_CREATE_ARCH_SYMLINK
> +#include <asm/arch/gpio.h>
> +#endif
> +#include <power/acpi_pmc.h>
> +
> +enum {
> +       PM1_STS         = 0x00,
> +       PM1_EN          = 0x02,
> +       PM1_CNT         = 0x04,
> +
> +       GPE0_STS        = 0x20,
> +       GPE0_EN         = 0x30,
> +};
> +
> +struct tco_regs {
> +       u32 tco_rld;
> +       u32 tco_sts;
> +       u32 tco1_cnt;
> +       u32 tco_tmr;
> +};
> +
> +enum {
> +       TCO_STS_TIMEOUT                 = 1 << 3,
> +       TCO_STS_SECOND_TO_STS           = 1 << 17,
> +       TCO1_CNT_HLT                    = 1 << 11,
> +};
> +
> +static void pmc_fill_pm_reg_info(struct udevice *dev)
> +{
> +       struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
> +       int i;
> +
> +       upriv->pm1_sts = inw(upriv->acpi_base + PM1_STS);
> +       upriv->pm1_en = inw(upriv->acpi_base + PM1_EN);
> +       upriv->pm1_cnt = inw(upriv->acpi_base + PM1_CNT);
> +
> +       log_debug("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
> +                 upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
> +
> +       for (i = 0; i < GPE0_REG_MAX; i++) {
> +               upriv->gpe0_sts[i] = inl(upriv->acpi_base + GPE0_STS + i * 4);
> +               upriv->gpe0_en[i] = inl(upriv->acpi_base + GPE0_EN + i * 4);
> +               log_debug("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
> +                         upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
> +       }
> +}
> +
> +int pmc_disable_tco_base(ulong tco_base)
> +{
> +       struct tco_regs *regs = (struct tco_regs *)tco_base;
> +
> +       debug("tco_base %lx = %x\n", (ulong)&regs->tco1_cnt, TCO1_CNT_HLT);
> +       setio_32(&regs->tco1_cnt, TCO1_CNT_HLT);
> +
> +       return 0;
> +}
> +
> +int pmc_init(struct udevice *dev)
> +{
> +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> +       int ret;
> +
> +       pmc_fill_pm_reg_info(dev);
> +       if (!ops->init)
> +               return -ENOSYS;
> +
> +       ret = ops->init(dev);
> +       if (ret)
> +               return log_msg_ret("Failed to init pmc", ret);
> +
> +#ifdef DEBUG
> +       pmc_dump_info(dev);
> +#endif
> +
> +       return 0;
> +}
> +
> +int pmc_prev_sleep_state(struct udevice *dev)
> +{
> +       struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
> +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> +       int prev_sleep_state = ACPI_S0; /* Default to S0 */
> +
> +       if (upriv->pm1_sts & WAK_STS) {
> +               switch (acpi_sleep_from_pm1(upriv->pm1_cnt)) {
> +               case ACPI_S3:
> +                       if (IS_ENABLED(HAVE_ACPI_RESUME))
> +                               prev_sleep_state = ACPI_S3;
> +                       break;
> +               case ACPI_S5:
> +                       prev_sleep_state = ACPI_S5;
> +                       break;
> +               default:
> +                       break;
> +               }
> +
> +               /* Clear SLP_TYP */
> +               outl(upriv->pm1_cnt & ~SLP_TYP, upriv->acpi_base + PM1_CNT);
> +       }
> +
> +       if (!ops->prev_sleep_state)
> +               return prev_sleep_state;
> +
> +       return ops->prev_sleep_state(dev, prev_sleep_state);
> +}
> +
> +int pmc_disable_tco(struct udevice *dev)
> +{
> +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> +
> +       pmc_fill_pm_reg_info(dev);
> +       if (!ops->disable_tco)
> +               return -ENOSYS;
> +
> +       return ops->disable_tco(dev);
> +}
> +
> +int pmc_global_reset_set_enable(struct udevice *dev, bool enable)
> +{
> +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> +
> +       if (!ops->global_reset_set_enable)
> +               return -ENOSYS;
> +
> +       return ops->global_reset_set_enable(dev, enable);
> +}
> +
> +void pmc_dump_info(struct udevice *dev)
> +{
> +       struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
> +       int i;
> +
> +       printf("Device: %s\n", dev->name);
> +       printf("ACPI base %x, pmc_bar0 %p, pmc_bar2 %p, gpe_cfg %p\n",
> +              upriv->acpi_base, upriv->pmc_bar0, upriv->pmc_bar2,
> +              upriv->gpe_cfg);
> +       printf("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
> +              upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
> +
> +       for (i = 0; i < GPE0_REG_MAX; i++) {
> +               printf("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
> +                      upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
> +       }
> +
> +       printf("prsts: %08x\n", upriv->prsts);
> +       printf("tco_sts:   %04x %04x\n", upriv->tco1_sts, upriv->tco2_sts);
> +       printf("gen_pmcon1: %08x gen_pmcon2: %08x gen_pmcon3: %08x\n",
> +              upriv->gen_pmcon1, upriv->gen_pmcon2, upriv->gen_pmcon3);
> +}
> +
> +int pmc_ofdata_to_uc_platdata(struct udevice *dev)
> +{
> +       struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
> +       int ret;
> +
> +       ret = dev_read_u32(dev, "gpe0-dwx-mask", &upriv->gpe0_dwx_mask);
> +       if (ret)
> +               return log_msg_ret("no gpe0-dwx-mask", ret);
> +       ret = dev_read_u32(dev, "gpe0-dwx-shift-base",
> +                          &upriv->gpe0_dwx_shift_base);
> +       if (ret)
> +               return log_msg_ret("no gpe0-dwx-shift-base", ret);
> +       ret = dev_read_u32(dev, "gpe0-sts", &upriv->gpe0_sts_reg);
> +       if (ret)
> +               return log_msg_ret("no gpe0-sts", ret);
> +       upriv->gpe0_sts_reg += upriv->acpi_base;
> +       ret = dev_read_u32(dev, "gpe0-en", &upriv->gpe0_en_reg);
> +       if (ret)
> +               return log_msg_ret("no gpe0-en", ret);
> +       upriv->gpe0_en_reg += upriv->acpi_base;
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(acpi_pmc) = {
> +       .id             = UCLASS_ACPI_PMC,
> +       .name           = "power-mgr",
> +       .per_device_auto_alloc_size     = sizeof(struct acpi_pmc_upriv),
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index f7f323752c2..d19ad1a12e6 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -28,6 +28,7 @@ enum uclass_id {
>         UCLASS_AXI_EMUL,        /* sandbox AXI bus device emulator */
>
>         /* U-Boot uclasses start here - in alphabetical order */
> +       UCLASS_ACPI_PMC,        /* (x86) Power-management controller (PMC) */
>         UCLASS_ADC,             /* Analog-to-digital converter */
>         UCLASS_AHCI,            /* SATA disk controller */
>         UCLASS_AUDIO_CODEC,     /* Audio codec with control and data path */
> diff --git a/include/power/acpi_pmc.h b/include/power/acpi_pmc.h
> new file mode 100644
> index 00000000000..1f50c23f5f8
> --- /dev/null
> +++ b/include/power/acpi_pmc.h
> @@ -0,0 +1,185 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2019 Google LLC
> + */
> +
> +#ifndef __ACPI_PMC_H
> +#define __ACPI_PMC_H
> +
> +enum {
> +       GPE0_REG_MAX    = 4,
> +};
> +
> +/**
> + * struct acpi_pmc_upriv - holds common data for the x86 PMC
> + *
> + * @pmc_bar0: Base address 0 of PMC
> + * @pmc_bar1: Base address 2 of PMC
> + * @acpi_base: Base address of ACPI block
> + * @pm1_sts: PM1 status
> + * @pm1_en: PM1 enable
> + * @pm1_cnt: PM1 control
> + * @gpe_cfg: Address of GPE_CFG register
> + * @gpe0_dwx_mask: Mask to use for each GPE0 (typically 7 or 0xf)
> + * @gpe0_dwx_shift_base: Base shift value to use for GPE0 (0 or 4)
> + * @gpe0_sts_req: GPE0 status register offset
> + * @gpe0_en_req: GPE0 enable register offset
> + * @gpe0_sts: GPE0 status values
> + * @gpe0_en: GPE0 enable values
> + * @gpe0_dw: GPE0 DW values
> + * @gpe0_count: Number of GPE0 registers
> + * @tco1_sts: TCO1 status
> + * @tco2_sts: TCO2 status
> + * @prsts: Power and reset status
> + * @gen_pmcon1: General power mgmt configuration 1
> + * @gen_pmcon2: General power mgmt configuration 2
> + * @gen_pmcon3: General power mgmt configuration 3
> + */
> +struct acpi_pmc_upriv {
> +       void *pmc_bar0;
> +       void *pmc_bar2;
> +       u32 acpi_base;
> +       u16 pm1_sts;
> +       u16 pm1_en;
> +       u32 pm1_cnt;
> +       u32 *gpe_cfg;
> +       u32 gpe0_dwx_mask;
> +       u32 gpe0_dwx_shift_base;
> +       u32 gpe0_sts_reg;
> +       u32 gpe0_en_reg;
> +       u32 gpe0_sts[GPE0_REG_MAX];
> +       u32 gpe0_en[GPE0_REG_MAX];
> +       u32 gpe0_dw[GPE0_REG_MAX];
> +       int gpe0_count;
> +       u16 tco1_sts;
> +       u16 tco2_sts;
> +       u32 prsts;
> +       u32 gen_pmcon1;
> +       u32 gen_pmcon2;
> +       u32 gen_pmcon3;
> +};
> +
> +struct acpi_pmc_ops {
> +       /**
> +        * init() - Set up the PMC for use
> +        *
> +        * This reads the current state of the PMC. Most of the state is read
> +        * automatically by the uclass since it is common.
> +        *
> +        * This is optional.
> +        *
> +        * @dev: PMC device to use
> +        * @return 0 if OK, -ve on error
> +        */
> +       int (*init)(struct udevice *dev);
> +
> +       /**
> +        * prev_sleep_state() - Get the previous sleep state (optional)
> +        *
> +        * This reads various state registers and returns the sleep state from
> +        * which the system woke. If this method is not provided, the uclass
> +        * will return a calculated value.
> +        *
> +        * This is optional.
> +        *
> +        * @dev: PMC device to use
> +        * @prev_sleep_state: Previous sleep state as calculated by the uclass.
> +        *      The method can use this as the return value or calculate its
> +        *      own.
> +        *
> +        * @return enum acpi_sleep_state indicating the previous sleep state
> +        *      (ACPI_S0, ACPI_S3 or ACPI_S5), or -ve on error
> +        */
> +       int (*prev_sleep_state)(struct udevice *dev, int prev_sleep_state);
> +
> +       /**
> +        * disable_tco() - Disable the timer/counter
> +        *
> +        * Disables the timer/counter in the PMC
> +        *
> +        * This is optional.
> +        *
> +        * @dev: PMC device to use
> +        * @return 0
> +        */
> +       int (*disable_tco)(struct udevice *dev);
> +
> +       /**
> +        * global_reset_set_enable() - Enable/Disable global reset
> +        *
> +        * Enable or disable global reset. If global reset is enabled, both hard
> +        * reset and soft reset will trigger global reset, where both host and
> +        * TXE are reset. This is cleared on cold boot, hard reset, soft reset
> +        * and Sx.
> +        *
> +        * This is optional.
> +        *
> +        * @dev: PMC device to use
> +        * @enable: true to enable global reset, false to disable
> +        * @return 0
> +        */
> +       int (*global_reset_set_enable)(struct udevice *dev, bool enable);
> +};
> +
> +#define acpi_pmc_get_ops(dev)  ((struct acpi_pmc_ops *)(dev)->driver->ops)
> +
> +/**
> + * init() - Set up the PMC for use
> + *
> + * This reads the current state of the PMC. This reads in the common registers,
> + * then calls the device's init() method to read the SoC-specific registers.
> + *
> + * @return 0 if OK, -ve on error
> + */
> +int pmc_init(struct udevice *dev);
> +
> +/**
> + * pmc_prev_sleep_state() - Get the previous sleep state
> + *
> + * This reads various state registers and returns the sleep state from
> + * which the system woke.
> + *
> + * @return enum acpi_sleep_state indicating the previous sleep state
> + *     (ACPI_S0, ACPI_S3 or ACPI_S5), or -ve on error
> + */
> +int pmc_prev_sleep_state(struct udevice *dev);
> +
> +/**
> + * pmc_disable_tco() - Disable the timer/counter
> + *
> + * Disables the timer/counter in the PMC
> + *
> + * @dev: PMC device to use
> + * @return 0
> + */
> +int pmc_disable_tco(struct udevice *dev);
> +
> +/**
> + * pmc_global_reset_set_enable() - Enable/Disable global reset
> + *
> + * Enable or disable global reset. If global reset is enabled, both hard
> + * reset and soft reset will trigger global reset, where both host and
> + * TXE are reset. This is cleared on cold boot, hard reset, soft reset
> + * and Sx.
> + *
> + * @dev: PMC device to use
> + * @enable: true to enable global reset, false to disable
> + * @return 0
> + */
> +int pmc_global_reset_set_enable(struct udevice *dev, bool enable);
> +
> +int pmc_ofdata_to_uc_platdata(struct udevice *dev);
> +
> +int pmc_disable_tco_base(ulong tco_base);
> +
> +void pmc_dump_info(struct udevice *dev);
> +
> +/**
> + * pmc_gpe_init() - Set up general-purpose events
> + *
> + * @dev: PMC device
> + * @return 0 if OK, -ve on error
> + */
> +int pmc_gpe_init(struct udevice *dev);
> +
> +#endif
> --

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited
  2019-10-28  7:12 ` Bin Meng
@ 2019-11-02  9:47   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:47 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 28, 2019 at 3:12 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:39 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > At present the value of the timer base is used to determine whether the
> > timer has been set up or not. It is true that the timer is essentially
> > never exactly 0 when it is read. However 'time 0' may indicate the time
> > that the machine was reset so it is useful to be able to denote that.
> >
> > Update the code to use a separate flag instead.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  arch/x86/include/asm/global_data.h | 1 +
> >  drivers/timer/tsc_timer.c          | 3 ++-
> >  2 files changed, 3 insertions(+), 1 deletion(-)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT
  2019-10-28  7:12   ` Bin Meng
@ 2019-11-02  9:49     ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:49 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 28, 2019 at 3:12 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > The x86 power unit handles power management. Support initing this device
> > which is modelled as a new type of system controller since there are no
> > operations needed.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > - Fix 'err-%d' typo
> >
> > Changes in v2: None
> >
> >  arch/x86/include/asm/cpu.h |  1 +
> >  arch/x86/lib/spl.c         | 40 ++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 41 insertions(+)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus
  2019-10-28  7:12   ` Bin Meng
@ 2019-11-02  9:49     ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:49 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 28, 2019 at 3:12 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > In TPL we try to minimise code size so do not include the PCI subsystem.
> > We can use fixed BARs and drivers can directly program the devices that
> > they need.
> >
> > However we do need to bind the devices on the PCI bus and without PCI this
> > does not ordinarily happen. As a work-around, define a fake PCI bus which
> > does this binding, but no other PCI operations. This is a convenient way
> > to ensure that we can use the same device tree for TPL, SPL and U-Boot
> > proper:
> >
> >    TPL    - CONFIG_TPL_PCI is not set (no auto-config, fake PCI bus)
> >    SPL    - CONFIG_SPL_PCI is set (no auto-config but with real PCI bus)
> >    U-Boot - CONFIG_PCI is set (full auto-config after relocation)
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > - Fix 'autoallocation' typo
> > - Improve wording in commit message
> >
> > Changes in v2: None
> >
> >  arch/x86/lib/tpl.c | 25 +++++++++++++++++++++++++
> >  1 file changed, 25 insertions(+)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function for TPL
  2019-10-28  7:50   ` Bin Meng
@ 2019-11-02  9:58     ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:58 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 28, 2019 at 3:50 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > For TPL we only need to set up the features and identify the CPU to a
> > basic level. Add a function to handle that.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  arch/x86/cpu/i386/cpu.c           | 8 ++++++++
> >  arch/x86/include/asm/u-boot-x86.h | 9 +++++++++
> >  2 files changed, 17 insertions(+)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init()
  2019-10-28  7:52   ` Bin Meng
@ 2019-11-02  9:58     ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:58 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 28, 2019 at 3:52 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > At present we call spl_init() before identifying the CPU. This is not a
> > good idea - e.g. if bootstage is enabled then it will try to set up the
> > timer which works better if the CPU is identified.
> >
> > Put explicit code at each entry pointer to identify the CPU.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  arch/x86/cpu/start_from_spl.S | 1 +
> >  arch/x86/lib/spl.c            | 4 ++++
> >  arch/x86/lib/tpl.c            | 5 +++++
> >  3 files changed, 10 insertions(+)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL
  2019-11-02  5:52   ` Bin Meng
@ 2019-11-02  9:58     ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:58 UTC (permalink / raw)
  To: u-boot

On Sat, Nov 2, 2019 at 1:52 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > We don't need to do this and it is done (in more detail) in U-Boot proper.
> > Drop this to save code space.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  arch/x86/lib/tpl.c | 5 -----
> >  1 file changed, 5 deletions(-)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args()
  2019-11-02  5:52   ` Bin Meng
@ 2019-11-02  9:58     ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-02  9:58 UTC (permalink / raw)
  To: u-boot

On Sat, Nov 2, 2019 at 1:52 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > We already a message indicating that U-Boot is about to jump to SPL, so
> > make this one a debug() to reduce code size.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  arch/x86/lib/tpl.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs
  2019-10-28  7:26   ` Bin Meng
@ 2019-11-02 18:25     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-02 18:25 UTC (permalink / raw)
  To: u-boot

Hi BIn,

On Mon, 28 Oct 2019 at 01:27, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Most of the timer-calibration methods are not needed on recent Intel CPUs
> > and just increase code size. Add an option to use the known-good way to
> > get the clock frequency in TPL. Size reduction is about 700 bytes.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  drivers/timer/Kconfig     | 9 +++++++++
> >  drivers/timer/tsc_timer.c | 7 +++++--
> >  2 files changed, 14 insertions(+), 2 deletions(-)
> >
>
> You mentioned in the v2 that this breaks bootstage, and will drop this
> patch. no?
> https://www.mail-archive.com/u-boot at lists.denx.de/msg344229.html

Ah yes I found the bug with that, and you've applied the patches. Will
update the commit message.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass
  2019-10-21  3:37 ` [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass Simon Glass
  2019-11-02  5:52   ` Bin Meng
@ 2019-11-04  8:02   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  1 sibling, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:02 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Intel x86 SoCs have a power manager/controller which handles several
> power-related aspects of the platform. Add a uclass for this, with a few
> useful operations.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Rename power-mgr uclass to acpi-pmc
>
> Changes in v2: None
>
>  drivers/power/Kconfig                    |   2 +
>  drivers/power/acpi_pmc/Kconfig           |  25 +++
>  drivers/power/acpi_pmc/Makefile          |   5 +
>  drivers/power/acpi_pmc/acpi-pmc-uclass.c | 191 +++++++++++++++++++++++
>  include/dm/uclass-id.h                   |   1 +
>  include/power/acpi_pmc.h                 | 185 ++++++++++++++++++++++
>  6 files changed, 409 insertions(+)
>  create mode 100644 drivers/power/acpi_pmc/Kconfig
>  create mode 100644 drivers/power/acpi_pmc/Makefile
>  create mode 100644 drivers/power/acpi_pmc/acpi-pmc-uclass.c
>  create mode 100644 include/power/acpi_pmc.h
>
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index 9495dca33b9..4b4f6d55568 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -4,6 +4,8 @@ source "drivers/power/domain/Kconfig"
>
>  source "drivers/power/pmic/Kconfig"
>
> +source "drivers/power/acpi_pmc/Kconfig"
> +
>  source "drivers/power/regulator/Kconfig"
>
>  choice
> diff --git a/drivers/power/acpi_pmc/Kconfig b/drivers/power/acpi_pmc/Kconfig
> new file mode 100644
> index 00000000000..472a61a9fd1
> --- /dev/null
> +++ b/drivers/power/acpi_pmc/Kconfig
> @@ -0,0 +1,25 @@
> +config ACPI_PMC
> +       bool "Power Manager (x86 PMC) support"
> +       help
> +         Enable support for an x86-style power-management controller which
> +         provides features including checking whether the system started from
> +         resume, powering off the system and enabling/disabling the reset
> +         mechanism.
> +
> +config SPL_ACPI_PMC
> +       bool "Power Manager (x86 PMC) support in SPL"
> +       default y if ACPI_PMC
> +       help
> +         Enable support for an x86-style power-management controller which
> +         provides features including checking whether the system started from
> +         resume, powering off the system and enabling/disabling the reset
> +         mechanism.
> +
> +config TPL_ACPI_PMC
> +       bool "Power Manager (x86 PMC) support in TPL"
> +       default y if ACPI_PMC
> +       help
> +         Enable support for an x86-style power-management controller which
> +         provides features including checking whether the system started from
> +         resume, powering off the system and enabling/disabling the reset
> +         mechanism.
> diff --git a/drivers/power/acpi_pmc/Makefile b/drivers/power/acpi_pmc/Makefile
> new file mode 100644
> index 00000000000..7c1ba05c9f3
> --- /dev/null
> +++ b/drivers/power/acpi_pmc/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright 2019 Google LLC
> +
> +obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += acpi-pmc-uclass.o
> diff --git a/drivers/power/acpi_pmc/acpi-pmc-uclass.c b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
> new file mode 100644
> index 00000000000..8800afecf10
> --- /dev/null
> +++ b/drivers/power/acpi_pmc/acpi-pmc-uclass.c
> @@ -0,0 +1,191 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 Google LLC
> + */
> +
> +#define LOG_CATEGORY UCLASS_ACPI_PMC
> +
> +#include <common.h>
> +#include <acpi_s3.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <asm/io.h>
> +#ifdef CONFIG_CREATE_ARCH_SYMLINK
> +#include <asm/arch/gpio.h>
> +#endif
> +#include <power/acpi_pmc.h>
> +
> +enum {
> +       PM1_STS         = 0x00,
> +       PM1_EN          = 0x02,
> +       PM1_CNT         = 0x04,
> +
> +       GPE0_STS        = 0x20,
> +       GPE0_EN         = 0x30,
> +};
> +
> +struct tco_regs {
> +       u32 tco_rld;
> +       u32 tco_sts;
> +       u32 tco1_cnt;
> +       u32 tco_tmr;
> +};
> +
> +enum {
> +       TCO_STS_TIMEOUT                 = 1 << 3,
> +       TCO_STS_SECOND_TO_STS           = 1 << 17,
> +       TCO1_CNT_HLT                    = 1 << 11,
> +};
> +
> +static void pmc_fill_pm_reg_info(struct udevice *dev)
> +{
> +       struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
> +       int i;
> +
> +       upriv->pm1_sts = inw(upriv->acpi_base + PM1_STS);
> +       upriv->pm1_en = inw(upriv->acpi_base + PM1_EN);
> +       upriv->pm1_cnt = inw(upriv->acpi_base + PM1_CNT);
> +
> +       log_debug("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
> +                 upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
> +
> +       for (i = 0; i < GPE0_REG_MAX; i++) {
> +               upriv->gpe0_sts[i] = inl(upriv->acpi_base + GPE0_STS + i * 4);
> +               upriv->gpe0_en[i] = inl(upriv->acpi_base + GPE0_EN + i * 4);
> +               log_debug("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
> +                         upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
> +       }
> +}
> +
> +int pmc_disable_tco_base(ulong tco_base)
> +{
> +       struct tco_regs *regs = (struct tco_regs *)tco_base;
> +
> +       debug("tco_base %lx = %x\n", (ulong)&regs->tco1_cnt, TCO1_CNT_HLT);
> +       setio_32(&regs->tco1_cnt, TCO1_CNT_HLT);
> +
> +       return 0;
> +}
> +
> +int pmc_init(struct udevice *dev)
> +{
> +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> +       int ret;
> +
> +       pmc_fill_pm_reg_info(dev);
> +       if (!ops->init)
> +               return -ENOSYS;
> +
> +       ret = ops->init(dev);
> +       if (ret)
> +               return log_msg_ret("Failed to init pmc", ret);
> +
> +#ifdef DEBUG
> +       pmc_dump_info(dev);
> +#endif
> +
> +       return 0;
> +}

I wonder shouldn't this be covered by the probe() method?

> +
> +int pmc_prev_sleep_state(struct udevice *dev)
> +{
> +       struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
> +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> +       int prev_sleep_state = ACPI_S0; /* Default to S0 */
> +
> +       if (upriv->pm1_sts & WAK_STS) {
> +               switch (acpi_sleep_from_pm1(upriv->pm1_cnt)) {
> +               case ACPI_S3:
> +                       if (IS_ENABLED(HAVE_ACPI_RESUME))
> +                               prev_sleep_state = ACPI_S3;
> +                       break;
> +               case ACPI_S5:
> +                       prev_sleep_state = ACPI_S5;
> +                       break;
> +               default:
> +                       break;
> +               }
> +
> +               /* Clear SLP_TYP */
> +               outl(upriv->pm1_cnt & ~SLP_TYP, upriv->acpi_base + PM1_CNT);
> +       }
> +
> +       if (!ops->prev_sleep_state)
> +               return prev_sleep_state;
> +
> +       return ops->prev_sleep_state(dev, prev_sleep_state);
> +}
> +

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass Simon Glass
@ 2019-11-04  8:23   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:23 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The Primary-to-Sideband bus (P2SB) is used to access various peripherals
> through memory-mapped I/O in a large chunk of PCI space. The space is
> segmented into different channels and peripherals are accessed by
> device-specific means within those channels. Devices should be added in
> the device tree as subnodes of the p2sb.
>
> This adds a uclass and enables it for sandbox.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  configs/sandbox_defconfig     |   1 +
>  configs/sandbox_spl_defconfig |   1 +
>  drivers/misc/Kconfig          |  33 ++++++
>  drivers/misc/Makefile         |   1 +
>  drivers/misc/p2sb-uclass.c    | 209 ++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h        |   1 +
>  include/p2sb.h                | 127 +++++++++++++++++++++
>  7 files changed, 373 insertions(+)
>  create mode 100644 drivers/misc/p2sb-uclass.c
>  create mode 100644 include/p2sb.h
>
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index 20ebc68997b..f8b78b8d7e1 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -150,6 +150,7 @@ CONFIG_PCI=y
>  CONFIG_DM_PCI=y
>  CONFIG_DM_PCI_COMPAT=y
>  CONFIG_PCI_SANDBOX=y
> +CONFIG_P2SB=y
>  CONFIG_PHY=y
>  CONFIG_PHY_SANDBOX=y
>  CONFIG_PINCTRL=y
> diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
> index 409b8a38d5e..c49e05ec319 100644
> --- a/configs/sandbox_spl_defconfig
> +++ b/configs/sandbox_spl_defconfig
> @@ -135,6 +135,7 @@ CONFIG_PCI=y
>  CONFIG_DM_PCI=y
>  CONFIG_DM_PCI_COMPAT=y
>  CONFIG_PCI_SANDBOX=y
> +CONFIG_P2SB=y
>  CONFIG_PHY=y
>  CONFIG_PHY_SANDBOX=y
>  CONFIG_PINCTRL=y
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index ba50893b432..1ed2e5d4aa2 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -217,6 +217,39 @@ config NUVOTON_NCT6102D
>           disable the legacy UART, the watchdog or other devices
>           in the Nuvoton Super IO chips on X86 platforms.
>
> +config P2SB
> +       bool "Intel Primary-to-Sideband Bus"
> +       depends on X86 || SANDBOX
> +       help
> +         This enables support for the Intel Primary-to-Sideband bus,
> +         abbreviated to P2SB. The P2SB is used to access various peripherals
> +         such as eSPI, GPIO, through memory-mapped I/O in a large chunk of PCI
> +         space. The space is segmented into different channels and peripherals
> +         are accessed by device-specific means within those channels. Devices
> +         should be added in the device tree as subnodes of the P2SB. A
> +         Peripheral Channel Register? (PCR) API is provided to access those

What does the ? mean? We are not sure what PCR stands for?

> +         devices - see pcr_readl(), etc.
> +
> +config SPL_P2SB
> +       bool "Intel Primary-to-Sideband Bus in SPL"
> +       depends on SPL && (X86 || SANDBOX)
> +       help
> +         The Primary-to-Sideband bus is used to access various peripherals
> +         through memory-mapped I/O in a large chunk of PCI space. The space is
> +         segmented into different channels and peripherals are accessed by
> +         device-specific means within those channels. Devices should be added
> +         in the device tree as subnodes of the p2sb.
> +
> +config TPL_P2SB
> +       bool "Intel Primary-to-Sideband Bus in TPL"
> +       depends on TPL && (X86 || SANDBOX)
> +       help
> +         The Primary-to-Sideband bus is used to access various peripherals
> +         through memory-mapped I/O in a large chunk of PCI space. The space is
> +         segmented into different channels and peripherals are accessed by
> +         device-specific means within those channels. Devices should be added
> +         in the device tree as subnodes of the p2sb.
> +
>  config PWRSEQ
>         bool "Enable power-sequencing drivers"
>         depends on DM
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 0001d105bae..840d9fa5e39 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -49,6 +49,7 @@ obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
>  obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
>  obj-$(CONFIG_NS87308) += ns87308.o
>  obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
> +obj-$(CONFIG_P2SB) += p2sb-uclass.o
>  obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
>  obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
>  obj-$(CONFIG_QFW) += qfw.o
> diff --git a/drivers/misc/p2sb-uclass.c b/drivers/misc/p2sb-uclass.c
> new file mode 100644
> index 00000000000..c4e663b5492
> --- /dev/null
> +++ b/drivers/misc/p2sb-uclass.c
> @@ -0,0 +1,209 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Uclass for Primary-to-sideband bus, used to access various peripherals
> + *
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <p2sb.h>
> +#include <spl.h>
> +#include <asm/io.h>
> +#include <dm/uclass-internal.h>
> +
> +#define PCR_COMMON_IOSF_1_0    1
> +
> +static void *_pcr_reg_address(struct udevice *dev, uint offset)
> +{
> +       struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
> +       struct udevice *p2sb = dev_get_parent(dev);
> +       struct p2sb_uc_priv *upriv = dev_get_uclass_priv(p2sb);
> +       uintptr_t reg_addr;
> +
> +       /* Create an address based off of port id and offset */
> +       reg_addr = upriv->mmio_base;
> +       reg_addr += pplat->pid << PCR_PORTID_SHIFT;
> +       reg_addr += offset;
> +
> +       return map_sysmem(reg_addr, 4);
> +}
> +
> +/*
> + * The mapping of addresses via the SBREG_BAR assumes the IOSF-SB
> + * agents are using 32-bit aligned accesses for their configuration
> + * registers. For IOSF versions greater than 1_0, IOSF-SB
> + * agents can use any access (8/16/32 bit aligned) for their
> + * configuration registers
> + */
> +static inline void check_pcr_offset_align(uint offset, uint size)
> +{
> +       const size_t align = PCR_COMMON_IOSF_1_0 ? sizeof(uint32_t) : size;
> +
> +       assert(IS_ALIGNED(offset, align));
> +}
> +
> +uint pcr_read32(struct udevice *dev, uint offset)
> +{
> +       void *ptr;
> +       uint val;
> +
> +       /* Ensure the PCR offset is correctly aligned */
> +       assert(IS_ALIGNED(offset, sizeof(uint32_t)));
> +
> +       ptr = _pcr_reg_address(dev, offset);
> +       val = readl(ptr);
> +       unmap_sysmem(ptr);
> +
> +       return val;
> +}
> +
> +uint pcr_read16(struct udevice *dev, uint offset)
> +{
> +       /* Ensure the PCR offset is correctly aligned */
> +       check_pcr_offset_align(offset, sizeof(uint16_t));
> +
> +       return readw(_pcr_reg_address(dev, offset));
> +}
> +
> +uint pcr_read8(struct udevice *dev, uint offset)
> +{
> +       /* Ensure the PCR offset is correctly aligned */
> +       check_pcr_offset_align(offset, sizeof(uint8_t));
> +
> +       return readb(_pcr_reg_address(dev, offset));
> +}
> +
> +/*
> + * After every write one needs to perform a 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.
> + */
> +static void write_completion(struct udevice *dev, uint offset)
> +{
> +       readl(_pcr_reg_address(dev, ALIGN_DOWN(offset, sizeof(uint32_t))));
> +}
> +
> +void pcr_write32(struct udevice *dev, uint offset, uint indata)
> +{
> +       /* Ensure the PCR offset is correctly aligned */
> +       assert(IS_ALIGNED(offset, sizeof(indata)));
> +
> +       writel(indata, _pcr_reg_address(dev, offset));
> +       /* Ensure the writes complete */
> +       write_completion(dev, offset);
> +}
> +
> +void pcr_write16(struct udevice *dev, uint offset, uint indata)
> +{
> +       /* Ensure the PCR offset is correctly aligned */
> +       check_pcr_offset_align(offset, sizeof(uint16_t));
> +
> +       writew(indata, _pcr_reg_address(dev, offset));
> +       /* Ensure the writes complete */
> +       write_completion(dev, offset);
> +}
> +
> +void pcr_write8(struct udevice *dev, uint offset, uint indata)
> +{
> +       /* Ensure the PCR offset is correctly aligned */
> +       check_pcr_offset_align(offset, sizeof(uint8_t));
> +
> +       writeb(indata, _pcr_reg_address(dev, offset));
> +       /* Ensure the writes complete */
> +       write_completion(dev, offset);
> +}
> +
> +void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set)
> +{
> +       uint data32;
> +
> +       data32 = pcr_read32(dev, offset);
> +       data32 &= ~clr;
> +       data32 |= set;
> +       pcr_write32(dev, offset, data32);
> +}
> +
> +void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set)
> +{
> +       uint data16;
> +
> +       data16 = pcr_read16(dev, offset);
> +       data16 &= ~clr;
> +       data16 |= set;
> +       pcr_write16(dev, offset, data16);
> +}
> +
> +void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set)
> +{
> +       uint data8;
> +
> +       data8 = pcr_read8(dev, offset);
> +       data8 &= ~clr;
> +       data8 |= set;
> +       pcr_write8(dev, offset, data8);
> +}
> +
> +int p2sb_set_port_id(struct udevice *dev, int portid)
> +{
> +       struct udevice *ps2b;
> +       struct p2sb_child_platdata *pplat;
> +
> +       if (!CONFIG_IS_ENABLED(OF_PLATDATA))
> +               return -ENOSYS;
> +
> +       uclass_find_first_device(UCLASS_P2SB, &ps2b);
> +       if (!ps2b)
> +               return -EDEADLK;
> +       dev->parent = ps2b;
> +
> +       /*
> +        * We must allocate this, since when the device was bound it did not
> +        * have a parent.
> +        * TODO(sjg at chromium.org): Add a parent pointer to child devices in dtoc
> +        */
> +       dev->parent_platdata = malloc(sizeof(*pplat));
> +       if (!dev->parent_platdata)
> +               return -ENOMEM;
> +       pplat = dev_get_parent_platdata(dev);
> +       pplat->pid = portid;
> +
> +       return 0;
> +}
> +
> +static int p2sb_child_post_bind(struct udevice *dev)
> +{
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> +       struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
> +       int ret;
> +       u32 pid;
> +
> +       ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
> +       if (ret)
> +               return ret;
> +       pplat->pid = pid;
> +#endif
> +
> +       return 0;
> +}
> +
> +static int p2sb_post_bind(struct udevice *dev)
> +{
> +       if (spl_phase() >= PHASE_SPL && !CONFIG_IS_ENABLED(OF_PLATDATA))
> +               return dm_scan_fdt_dev(dev);
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(p2sb) = {
> +       .id             = UCLASS_P2SB,
> +       .name           = "p2sb",
> +       .per_device_auto_alloc_size = sizeof(struct p2sb_uc_priv),
> +       .post_bind      = p2sb_post_bind,
> +       .child_post_bind = p2sb_child_post_bind,
> +       .per_child_platdata_auto_alloc_size =
> +               sizeof(struct p2sb_child_platdata),
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index d19ad1a12e6..6ae9138ca3d 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -70,6 +70,7 @@ enum uclass_id {
>         UCLASS_NOP,             /* No-op devices */
>         UCLASS_NORTHBRIDGE,     /* Intel Northbridge / SDRAM controller */
>         UCLASS_NVME,            /* NVM Express device */
> +       UCLASS_P2SB,            /* (x86) Primary-to-Sideband Bus */
>         UCLASS_PANEL,           /* Display panel, such as an LCD */
>         UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
>         UCLASS_PCH,             /* x86 platform controller hub */
> diff --git a/include/p2sb.h b/include/p2sb.h
> new file mode 100644
> index 00000000000..370f127058c
> --- /dev/null
> +++ b/include/p2sb.h
> @@ -0,0 +1,127 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#ifndef __p2sb_h
> +#define __p2sb_h
> +
> +/* Port Id lives in bits 23:16 and register offset lives in 15:0 of address */
> +#define PCR_PORTID_SHIFT       16
> +
> +/**
> + * struct p2sb_child_platdata - Information about each child of a p2sb device
> + *
> + * @pid: Port ID for this child
> + */
> +struct p2sb_child_platdata {
> +       uint pid;
> +};
> +
> +/**
> + * struct p2sb_uc_priv - information for the uclass about each device
> + *
> + * This must be set up by the driver when it is probed
> + *
> + * @mmio_base: Base address of P2SB region
> + */
> +struct p2sb_uc_priv {
> +       uint mmio_base;
> +};
> +
> +/**
> + * struct p2sb_ops - Operations for the P2SB (none at present)
> + */
> +struct p2sb_ops {
> +};
> +
> +#define p2sb_get_ops(dev)        ((struct p2sb_ops *)(dev)->driver->ops)
> +
> +/**
> + * pcr_read32/16/8() - Read from a PCR device
> + *
> + * Reads data from a PCR device within the P2SB
> + *
> + * @dev: Device to read from
> + * @offset: Offset within device to read
> + * @return value read
> + */
> +uint pcr_read32(struct udevice *dev, uint offset);
> +uint pcr_read16(struct udevice *dev, uint offset);
> +uint pcr_read8(struct udevice *dev, uint offset);
> +
> +/**
> + * pcr_read32/16/8() - Write to a PCR device
> + *
> + * Writes data to a PCR device within the P2SB

Read data

> + *
> + * @dev: Device to write to
> + * @offset: Offset within device to write
> + * @data: Data to write
> + */
> +void pcr_write32(struct udevice *dev, uint offset, uint data);
> +void pcr_write16(struct udevice *dev, uint offset, uint data);
> +void pcr_write8(struct udevice *dev, uint offset, uint data);
> +
> +/**
> + * pcr_clrsetbits32/16/8() - Update a PCR device
> + *
> + * Updates dat in a PCR device within the P2SB
> + *
> + * This reads from the device, clears and set bits, then writes back.
> + *
> + * new_data = (old_data & ~clr) | set
> + *
> + * @dev: Device to update
> + * @offset: Offset within device to update
> + * @clr: Bits to clear after reading
> + * @set: Bits to set before writing
> + */
> +void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set);
> +void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set);
> +void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set);
> +
> +static inline void pcr_setbits32(struct udevice *dev, uint offset, uint set)
> +{
> +       return pcr_clrsetbits32(dev, offset, 0, set);
> +}
> +
> +static inline void pcr_setbits16(struct udevice *dev, uint offset, uint set)
> +{
> +       return pcr_clrsetbits16(dev, offset, 0, set);
> +}
> +
> +static inline void pcr_setbits8(struct udevice *dev, uint offset, uint set)
> +{
> +       return pcr_clrsetbits8(dev, offset, 0, set);
> +}
> +
> +static inline void pcr_clrbits32(struct udevice *dev, uint offset, uint clr)
> +{
> +       return pcr_clrsetbits32(dev, offset, clr, 0);
> +}
> +
> +static inline void pcr_clrbits16(struct udevice *dev, uint offset, uint clr)
> +{
> +       return pcr_clrsetbits16(dev, offset, clr, 0);
> +}
> +
> +static inline void pcr_clrbits8(struct udevice *dev, uint offset, uint clr)
> +{
> +       return pcr_clrsetbits8(dev, offset, clr, 0);
> +}
> +
> +/**
> + * p2sb_set_port_id() - Set the port ID for a p2sb child device
> + *
> + * This must be called in a device's bind() method when OF_PLATDATA is used
> + * since the uclass cannot access the device's of-platdata.
> + *
> + * @dev: Child device (whose parent is UCLASS_P2SB)
> + * @portid: Port ID of child device
> + * @return 0 if OK, -ENODEV is the p2sb device could not be found
> + */
> +int p2sb_set_port_id(struct udevice *dev, int portid);
> +
> +#endif
> --

I still are not sure P2SB is generic enough to merit a uclass driver.

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 037/108] sandbox: Add PCI driver and test for p2sb
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 037/108] sandbox: Add PCI driver and test for p2sb Simon Glass
@ 2019-11-04  8:36   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add a sandbox driver and PCI-device emulator for p2sb. Also add a test
> which uses a simple 'adder' driver to test the p2sb functionality.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Fix build errors in sandbox_spl, etc
>
> Changes in v2: None
>
>  arch/sandbox/cpu/state.c           |   1 +
>  arch/sandbox/dts/test.dts          |  13 ++
>  arch/sandbox/include/asm/test.h    |  10 ++
>  configs/sandbox64_defconfig        |   2 +
>  configs/sandbox_flattree_defconfig |   3 +
>  configs/sandbox_spl_defconfig      |   2 +
>  configs/tools-only_defconfig       |   2 +
>  drivers/core/uclass.c              |   4 +-
>  drivers/misc/Makefile              |   2 +
>  drivers/misc/p2sb_emul.c           | 272 +++++++++++++++++++++++++++++
>  drivers/misc/p2sb_sandbox.c        |  44 +++++
>  drivers/misc/sandbox_adder.c       |  60 +++++++
>  test/dm/Makefile                   |   1 +
>  test/dm/p2sb.c                     |  28 +++
>  14 files changed, 442 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/misc/p2sb_emul.c
>  create mode 100644 drivers/misc/p2sb_sandbox.c
>  create mode 100644 drivers/misc/sandbox_adder.c
>  create mode 100644 test/dm/p2sb.c
>
> diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
> index dee5fde4f73..cd46e000f5e 100644
> --- a/arch/sandbox/cpu/state.c
> +++ b/arch/sandbox/cpu/state.c
> @@ -356,6 +356,7 @@ void state_reset_for_test(struct sandbox_state *state)
>         /* No reset yet, so mark it as such. Always allow power reset */
>         state->last_sysreset = SYSRESET_COUNT;
>         state->sysreset_allowed[SYSRESET_POWER_OFF] = true;
> +       state->allow_memio = false;

A separate patch?

>
>         memset(&state->wdt, '\0', sizeof(state->wdt));
>         memset(state->spi, '\0', sizeof(state->spi));
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index 5c1093df282..24631770544 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -467,6 +467,16 @@
>                                0x01000810 0 0 0 0>;
>                         sandbox,emul = <&swap_case_emul0_1>;
>                 };
> +               p2sb-pci at 2,0 {
> +                       compatible = "sandbox,p2sb";
> +                       reg = <0x02001010 0 0 0 0>;
> +                       sandbox,emul = <&p2sb_emul>;
> +
> +                       adder {
> +                               intel,p2sb-port-id = <3>;
> +                               compatible = "sandbox,adder";
> +                       };
> +               };
>                 pci at 1e,0 {
>                         compatible = "sandbox,pmc";
>                         reg = <0xf000 0 0 0 0>;
> @@ -498,6 +508,9 @@
>                 swap_case_emul0_1f: emul0 at 1f,0 {
>                         compatible = "sandbox,swap-case";
>                 };
> +               p2sb_emul: emul at 2,0 {
> +                       compatible = "sandbox,p2sb-emul";
> +               };
>                 pmc_emul1e: emul at 1e,0 {
>                         compatible = "sandbox,pmc-emul";
>                 };
> diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
> index 7f9e7fc26f5..77fff529e19 100644
> --- a/arch/sandbox/include/asm/test.h
> +++ b/arch/sandbox/include/asm/test.h
> @@ -14,6 +14,7 @@
>  #define SANDBOX_PCI_VENDOR_ID          0x1234
>  #define SANDBOX_PCI_SWAP_CASE_EMUL_ID  0x5678
>  #define SANDBOX_PCI_PMC_EMUL_ID                0x5677
> +#define SANDBOX_PCI_P2SB_EMUL_ID       0x5676
>  #define SANDBOX_PCI_CLASS_CODE         PCI_CLASS_CODE_COMM
>  #define SANDBOX_PCI_CLASS_SUB_CODE     PCI_CLASS_SUB_CODE_COMM_SERIAL
>
> @@ -214,4 +215,13 @@ int sandbox_get_pci_ep_irq_count(struct udevice *dev);
>   */
>  uint sandbox_pci_read_bar(u32 barval, int type, uint size);
>
> +/**
> + * sandbox_set_enable_memio() - Enable memory-mapped I/O read/write
> + *
> + * Normally readl(), writel() and the like are nops on sandbox. If this function
> + * is called with true, those function do real memory accesses. This is useful
> + * for certain tests.
> + */
> +void sandbox_set_enable_memio(bool enable);
> +

A separate patch?

>  #endif
> diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
> index 1fea683d892..4c86141ffb1 100644
> --- a/configs/sandbox64_defconfig
> +++ b/configs/sandbox64_defconfig
> @@ -81,6 +81,8 @@ CONFIG_DEVRES=y
>  CONFIG_DEBUG_DEVRES=y
>  CONFIG_ADC=y
>  CONFIG_ADC_SANDBOX=y
> +CONFIG_AXI=y
> +CONFIG_AXI_SANDBOX=y
>  CONFIG_CLK=y
>  CONFIG_CPU=y
>  CONFIG_DM_DEMO=y
> diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
> index 898815fe531..230d65b14a7 100644
> --- a/configs/sandbox_flattree_defconfig
> +++ b/configs/sandbox_flattree_defconfig
> @@ -65,6 +65,8 @@ CONFIG_DEVRES=y
>  CONFIG_DEBUG_DEVRES=y
>  CONFIG_ADC=y
>  CONFIG_ADC_SANDBOX=y
> +CONFIG_AXI=y
> +CONFIG_AXI_SANDBOX=y
>  CONFIG_CLK=y
>  CONFIG_CLK_COMPOSITE_CCF=y
>  CONFIG_SANDBOX_CLK_CCF=y
> @@ -116,6 +118,7 @@ CONFIG_PCI=y
>  CONFIG_DM_PCI=y
>  CONFIG_DM_PCI_COMPAT=y
>  CONFIG_PCI_SANDBOX=y
> +CONFIG_P2SB=y
>  CONFIG_PHY=y
>  CONFIG_PHY_SANDBOX=y
>  CONFIG_PINCTRL=y
> diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
> index c49e05ec319..405b6015474 100644
> --- a/configs/sandbox_spl_defconfig
> +++ b/configs/sandbox_spl_defconfig
> @@ -86,6 +86,8 @@ CONFIG_DEBUG_DEVRES=y
>  # CONFIG_SPL_SIMPLE_BUS is not set
>  CONFIG_ADC=y
>  CONFIG_ADC_SANDBOX=y
> +CONFIG_AXI=y
> +CONFIG_AXI_SANDBOX=y
>  CONFIG_CLK=y
>  CONFIG_CPU=y
>  CONFIG_DM_DEMO=y
> diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig
> index 4808b498502..35f5ca74065 100644
> --- a/configs/tools-only_defconfig
> +++ b/configs/tools-only_defconfig
> @@ -11,6 +11,8 @@ CONFIG_OF_HOSTFILE=y
>  CONFIG_DEFAULT_DEVICE_TREE="sandbox"
>  CONFIG_IP_DEFRAG=y
>  # CONFIG_UDP_FUNCTION_FASTBOOT is not set
> +CONFIG_AXI=y
> +CONFIG_AXI_SANDBOX=y
>  CONFIG_SANDBOX_GPIO=y
>  CONFIG_PCI=y
>  CONFIG_DM_PCI=y
> diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
> index 36f4d1c289d..57f619cca3b 100644
> --- a/drivers/core/uclass.c
> +++ b/drivers/core/uclass.c
> @@ -56,8 +56,8 @@ static int uclass_add(enum uclass_id id, struct uclass **ucp)
>         *ucp = NULL;
>         uc_drv = lists_uclass_lookup(id);
>         if (!uc_drv) {
> -               debug("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
> -                     id);
> +               printf("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
> +                      id);

Looks unrelated to this patch.

>                 /*
>                  * Use a strange error to make this case easier to find. When
>                  * a uclass is not available it can prevent driver model from
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 840d9fa5e39..363864454bd 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -10,8 +10,10 @@ obj-$(CONFIG_$(SPL_TPL_)CROS_EC_SANDBOX) += cros_ec_sandbox.o
>  obj-$(CONFIG_$(SPL_TPL_)CROS_EC_LPC) += cros_ec_lpc.o
>
>  ifndef CONFIG_SPL_BUILD
> +obj-$(CONFIG_SANDBOX) += sandbox_adder.o
>  obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
>  obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
> +obj-$(CONFIG_SANDBOX) += p2sb_sandbox.o p2sb_emul.o
>  obj-$(CONFIG_SANDBOX) += swap_case.o
>  endif
>
> diff --git a/drivers/misc/p2sb_emul.c b/drivers/misc/p2sb_emul.c
> new file mode 100644
> index 00000000000..c3795c59c08
> --- /dev/null
> +++ b/drivers/misc/p2sb_emul.c
> @@ -0,0 +1,272 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * PCI emulation device for an x86 Primary-to-Sideband bus
> + *
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#define LOG_CATEGORY UCLASS_MISC
> +#define LOG_DEBUG
> +
> +#include <common.h>
> +#include <axi.h>
> +#include <dm.h>
> +#include <pci.h>
> +#include <asm/test.h>
> +#include <p2sb.h>
> +
> +/**
> + * struct p2sb_emul_platdata - platform data for this device
> + *
> + * @command:   Current PCI command value
> + * @bar:       Current base address values
> + */
> +struct p2sb_emul_platdata {
> +       u16 command;
> +       u32 bar[6];
> +};
> +
> +enum {
> +       /* This emulator supports 16 different devices */
> +       MEMMAP_SIZE     = 16 << PCR_PORTID_SHIFT,
> +};
> +
> +static struct pci_bar {
> +       int type;
> +       u32 size;
> +} barinfo[] = {
> +       { PCI_BASE_ADDRESS_MEM_TYPE_32, MEMMAP_SIZE },
> +       { 0, 0 },
> +       { 0, 0 },
> +       { 0, 0 },
> +       { 0, 0 },
> +       { 0, 0 },
> +};
> +
> +struct p2sb_emul_priv {
> +       u8 regs[16];
> +};
> +
> +static int sandbox_p2sb_emul_read_config(struct udevice *emul, uint offset,
> +                                        ulong *valuep, enum pci_size_t size)
> +{
> +       struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
> +
> +       switch (offset) {
> +       case PCI_COMMAND:
> +               *valuep = plat->command;
> +               break;
> +       case PCI_HEADER_TYPE:
> +               *valuep = PCI_HEADER_TYPE_NORMAL;
> +               break;
> +       case PCI_VENDOR_ID:
> +               *valuep = SANDBOX_PCI_VENDOR_ID;
> +               break;
> +       case PCI_DEVICE_ID:
> +               *valuep = SANDBOX_PCI_P2SB_EMUL_ID;
> +               break;
> +       case PCI_CLASS_DEVICE:
> +               if (size == PCI_SIZE_8) {
> +                       *valuep = SANDBOX_PCI_CLASS_SUB_CODE;
> +               } else {
> +                       *valuep = (SANDBOX_PCI_CLASS_CODE << 8) |
> +                                       SANDBOX_PCI_CLASS_SUB_CODE;
> +               }
> +               break;
> +       case PCI_CLASS_CODE:
> +               *valuep = SANDBOX_PCI_CLASS_CODE;
> +               break;
> +       case PCI_BASE_ADDRESS_0:
> +       case PCI_BASE_ADDRESS_1:
> +       case PCI_BASE_ADDRESS_2:
> +       case PCI_BASE_ADDRESS_3:
> +       case PCI_BASE_ADDRESS_4:
> +       case PCI_BASE_ADDRESS_5: {
> +               int barnum;
> +               u32 *bar;
> +
> +               barnum = pci_offset_to_barnum(offset);
> +               bar = &plat->bar[barnum];
> +
> +               *valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type,
> +                                              barinfo[barnum].size);
> +               break;
> +       }
> +       case PCI_CAPABILITY_LIST:
> +               *valuep = PCI_CAP_ID_PM_OFFSET;
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static int sandbox_p2sb_emul_write_config(struct udevice *emul, uint offset,
> +                                         ulong value, enum pci_size_t size)
> +{
> +       struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
> +
> +       switch (offset) {
> +       case PCI_COMMAND:
> +               plat->command = value;
> +               break;
> +       case PCI_BASE_ADDRESS_0:
> +       case PCI_BASE_ADDRESS_1: {
> +               int barnum;
> +               u32 *bar;
> +
> +               barnum = pci_offset_to_barnum(offset);
> +               bar = &plat->bar[barnum];
> +
> +               log_debug("w bar %d=%lx\n", barnum, value);
> +               *bar = value;
> +               /* space indicator (bit#0) is read-only */
> +               *bar |= barinfo[barnum].type;
> +               break;
> +       }
> +       }
> +
> +       return 0;
> +}
> +
> +static int sandbox_p2sb_emul_find_bar(struct udevice *emul, unsigned int addr,
> +                                     int *barnump, unsigned int *offsetp)
> +{
> +       struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
> +       int barnum;
> +
> +       for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) {
> +               unsigned int size = barinfo[barnum].size;
> +               u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE;
> +
> +               if (addr >= base && addr < base + size) {
> +                       *barnump = barnum;
> +                       *offsetp = addr - base;
> +                       return 0;
> +               }
> +       }
> +       *barnump = -1;
> +
> +       return -ENOENT;
> +}
> +
> +static int sandbox_p2sb_emul_read_io(struct udevice *dev, unsigned int addr,
> +                                    ulong *valuep, enum pci_size_t size)
> +{
> +       unsigned int offset;
> +       int barnum;
> +       int ret;
> +
> +       ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
> +       if (ret)
> +               return ret;
> +
> +       if (barnum == 4)
> +               *valuep = offset;
> +       else if (barnum == 0)
> +               *valuep = offset;
> +
> +       return 0;
> +}
> +
> +static int sandbox_p2sb_emul_write_io(struct udevice *dev, unsigned int addr,
> +                                     ulong value, enum pci_size_t size)
> +{
> +       unsigned int offset;
> +       int barnum;
> +       int ret;
> +
> +       ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static int find_p2sb_channel(struct udevice *emul, uint offset,
> +                            struct udevice **devp)
> +{
> +       uint pid = offset >> PCR_PORTID_SHIFT;
> +       struct udevice *p2sb, *dev;
> +       int ret;
> +
> +       ret = sandbox_pci_get_client(emul, &p2sb);
> +       if (ret)
> +               return log_msg_ret("No client", ret);
> +
> +       device_foreach_child(dev, p2sb) {
> +               struct p2sb_child_platdata *pplat =
> +                        dev_get_parent_platdata(dev);
> +
> +               log_debug("   - child %s, pid %d, want %d\n", dev->name,
> +                         pplat->pid, pid);
> +               if (pid == pplat->pid) {
> +                       *devp = dev;
> +                       return 0;
> +               }
> +       }
> +
> +       return -ENOENT;
> +}
> +
> +static int sandbox_p2sb_emul_map_physmem(struct udevice *dev,
> +                                        phys_addr_t addr, unsigned long *lenp,
> +                                        void **ptrp)
> +{
> +       struct p2sb_emul_priv *priv = dev_get_priv(dev);
> +       struct udevice *child;
> +       unsigned int offset;
> +       int barnum;
> +       int ret;
> +
> +       log_debug("map %x: ", (uint)addr);
> +       ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
> +       if (ret)
> +               return log_msg_ret("Cannot find bar", ret);
> +       log_debug("bar %d, offset %x\n", barnum, offset);
> +
> +       if (barnum != 0)
> +               return log_msg_ret("Unknown BAR", -EINVAL);
> +
> +       ret = find_p2sb_channel(dev, offset, &child);
> +       if (ret)
> +               return log_msg_ret("Cannot find channel", ret);
> +
> +       offset &= ((1 << PCR_PORTID_SHIFT) - 1);
> +       ret = axi_read(child, offset, priv->regs, AXI_SIZE_32);
> +       if (ret)
> +               return log_msg_ret("Child read failed", ret);
> +       *ptrp = priv->regs + (offset & 3);
> +       *lenp = 4;
> +
> +       return 0;
> +}
> +
> +static struct dm_pci_emul_ops sandbox_p2sb_emul_emul_ops = {
> +       .read_config = sandbox_p2sb_emul_read_config,
> +       .write_config = sandbox_p2sb_emul_write_config,
> +       .read_io = sandbox_p2sb_emul_read_io,
> +       .write_io = sandbox_p2sb_emul_write_io,
> +       .map_physmem = sandbox_p2sb_emul_map_physmem,
> +};
> +
> +static const struct udevice_id sandbox_p2sb_emul_ids[] = {
> +       { .compatible = "sandbox,p2sb-emul" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(sandbox_p2sb_emul_emul) = {
> +       .name           = "sandbox_p2sb_emul_emul",
> +       .id             = UCLASS_PCI_EMUL,
> +       .of_match       = sandbox_p2sb_emul_ids,
> +       .ops            = &sandbox_p2sb_emul_emul_ops,
> +       .priv_auto_alloc_size = sizeof(struct p2sb_emul_priv),
> +       .platdata_auto_alloc_size = sizeof(struct p2sb_emul_platdata),
> +};
> +
> +static struct pci_device_id sandbox_p2sb_emul_supported[] = {
> +       { PCI_VDEVICE(SANDBOX, SANDBOX_PCI_PMC_EMUL_ID) },
> +       {},
> +};
> +
> +U_BOOT_PCI_DEVICE(sandbox_p2sb_emul_emul, sandbox_p2sb_emul_supported);
> diff --git a/drivers/misc/p2sb_sandbox.c b/drivers/misc/p2sb_sandbox.c
> new file mode 100644
> index 00000000000..2337df9951d
> --- /dev/null
> +++ b/drivers/misc/p2sb_sandbox.c
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Sandbox P2SB for testing
> + *
> + * Copyright 2019 Google LLC
> + */
> +
> +#define LOG_CATEGORY UCLASS_P2SB
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <asm/io.h>
> +#include <p2sb.h>
> +
> +struct sandbox_p2sb_priv {
> +       ulong base;
> +};
> +
> +static int sandbox_p2sb_probe(struct udevice *dev)
> +{
> +       struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev);
> +
> +       upriv->mmio_base = dm_pci_read_bar32(dev, 0);
> +       printf("mmio base %x\n", upriv->mmio_base);
> +
> +       return 0;
> +}
> +
> +static struct p2sb_ops sandbox_p2sb_ops = {
> +};

Could this be dropped, since it's an empty struct?

> +
> +static const struct udevice_id sandbox_p2sb_ids[] = {
> +       { .compatible = "sandbox,p2sb" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(p2sb_sandbox) = {
> +       .name = "pmic_pm8916",

The name does not look correct.

> +       .id = UCLASS_P2SB,
> +       .of_match = sandbox_p2sb_ids,
> +       .probe = sandbox_p2sb_probe,
> +       .ops = &sandbox_p2sb_ops,
> +       .priv_auto_alloc_size = sizeof(struct sandbox_p2sb_priv),
> +};
> diff --git a/drivers/misc/sandbox_adder.c b/drivers/misc/sandbox_adder.c
> new file mode 100644
> index 00000000000..df262e62555
> --- /dev/null
> +++ b/drivers/misc/sandbox_adder.c
> @@ -0,0 +1,60 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Sandbox adder for p2sb testing
> + *
> + * Copyright 2019 Google LLC
> + */
> +
> +#define LOG_CATEGORY UCLASS_MISC
> +
> +#include <common.h>
> +#include <axi.h>
> +#include <dm.h>
> +#include <misc.h>
> +#include <p2sb.h>
> +#include <asm/io.h>
> +
> +struct sandbox_adder_priv {
> +       ulong base;
> +};
> +
> +int sandbox_adder_read(struct udevice *dev, ulong address, void *data,
> +                      enum axi_size_t size)
> +{
> +       struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
> +       u32 *val = data;
> +
> +       *val = pplat->pid << 24 | address;
> +
> +       return 0;
> +}
> +
> +int sandbox_adder_write(struct udevice *dev, ulong address, void *data,
> +                       enum axi_size_t size)
> +{
> +       return 0;
> +}
> +
> +static int sandbox_adder_probe(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +static struct axi_ops sandbox_adder_ops = {
> +       .read   = sandbox_adder_read,
> +       .write  = sandbox_adder_write,
> +};
> +
> +static const struct udevice_id sandbox_adder_ids[] = {
> +       { .compatible = "sandbox,adder" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(adder_sandbox) = {
> +       .name = "sandbox_adder",
> +       .id = UCLASS_AXI,
> +       .of_match = sandbox_adder_ids,
> +       .probe = sandbox_adder_probe,
> +       .ops = &sandbox_adder_ops,
> +       .priv_auto_alloc_size = sizeof(struct sandbox_adder_priv),
> +};
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 10a19a00c90..129ccb3b496 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -32,6 +32,7 @@ obj-y += ofnode.o
>  obj-$(CONFIG_OSD) += osd.o
>  obj-$(CONFIG_DM_VIDEO) += panel.o
>  obj-$(CONFIG_DM_PCI) += pci.o
> +obj-$(CONFIG_P2SB) += p2sb.o
>  obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o
>  obj-$(CONFIG_PCH) += pch.o
>  obj-$(CONFIG_PHY) += phy.o
> diff --git a/test/dm/p2sb.c b/test/dm/p2sb.c
> new file mode 100644
> index 00000000000..ccb75cf3753
> --- /dev/null
> +++ b/test/dm/p2sb.c
> @@ -0,0 +1,28 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Test for Primary-to-Sideband bus (P2SB)
> + *
> + * Copyright 2019 Google LLC
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <p2sb.h>
> +#include <asm/test.h>
> +#include <dm/test.h>
> +#include <test/ut.h>
> +
> +/* Base test of the PMC uclass */
> +static int dm_test_p2sb_base(struct unit_test_state *uts)
> +{
> +       struct udevice *dev;
> +
> +       sandbox_set_enable_memio(true);
> +       ut_assertok(uclass_get_device_by_name(UCLASS_AXI, "adder", &dev));
> +       ut_asserteq(0x03000004, pcr_read32(dev, 4));
> +       ut_asserteq(0x300, pcr_read16(dev, 6));
> +       ut_asserteq(4, pcr_read8(dev, 4));
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_p2sb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 038/108] x86: Move UCLASS_IRQ into a separate file
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 038/108] x86: Move UCLASS_IRQ into a separate file Simon Glass
@ 2019-11-04  8:41   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:41 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Update this uclass to support the needs of the apollolake ITSS. It
> supports four operations.
>
> Move the uclass into a separate directory so that sandbox can use it too.
> Add a new Kconfig to control it and enable this on x86.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add two more operations to IRQ
> - Use the IRQ uclass instead of creating a new ITSS uclass
>
> Changes in v2: None
>
>  arch/Kconfig              |  1 +
>  arch/x86/cpu/irq.c        |  5 ---
>  drivers/misc/Kconfig      |  9 ++++
>  drivers/misc/Makefile     |  2 +
>  drivers/misc/irq-uclass.c | 53 +++++++++++++++++++++++
>  include/irq.h             | 88 +++++++++++++++++++++++++++++++++++++++
>  6 files changed, 153 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/misc/irq-uclass.c
>  create mode 100644 include/irq.h
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index e1f1fcd275b..6865e1f909e 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -186,6 +186,7 @@ config X86
>         imply USB_HOST_ETHER
>         imply PCH
>         imply RTC_MC146818
> +       imply IRQ
>
>         # Thing to enable for when SPL/TPL are enabled: SPL
>         imply SPL_DM
> diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
> index 3adc155818c..cb183496b7a 100644
> --- a/arch/x86/cpu/irq.c
> +++ b/arch/x86/cpu/irq.c
> @@ -370,8 +370,3 @@ U_BOOT_DRIVER(irq_router_drv) = {
>         .probe          = irq_router_probe,
>         .priv_auto_alloc_size = sizeof(struct irq_router),
>  };
> -
> -UCLASS_DRIVER(irq) = {
> -       .id             = UCLASS_IRQ,
> -       .name           = "irq",
> -};
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 1ed2e5d4aa2..7db5c15d999 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -194,6 +194,15 @@ config FSL_SEC_MON
>           Security Monitor can be transitioned on any security failures,
>           like software violations or hardware security violations.
>
> +config IRQ
> +       bool "Intel Interrupt controller"
> +       depends on X86 || SANDBOX
> +       help
> +         This enabled support for Intel interrupt controllers, including ITSS.

nits: enables

> +         Some devices have extra features, such as apollolake. The
> +         device has its own uclass since there are several operations
> +         involved.
> +
>  config JZ4780_EFUSE
>         bool "Ingenic JZ4780 eFUSE support"
>         depends on ARCH_JZ47XX
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 363864454bd..9a0c6f08dec 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -41,9 +41,11 @@ obj-$(CONFIG_FS_LOADER) += fs_loader.o
>  obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
>  obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
>  obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
> +obj-$(CONFIG_IRQ) += irq-uclass.o
>  obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
>  obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
>  obj-$(CONFIG_IMX8) += imx8/
> +obj-$(CONFIG_ITSS) += itss-uclass.o

This should be dropped

>  obj-$(CONFIG_LED_STATUS) += status_led.o
>  obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
>  obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
> diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
> new file mode 100644
> index 00000000000..d5182cf1497
> --- /dev/null
> +++ b/drivers/misc/irq-uclass.c
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <irq.h>
> +
> +int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
> +{
> +       const struct irq_ops *ops = irq_get_ops(dev);
> +
> +       if (!ops->route_pmc_gpio_gpe)
> +               return -ENOSYS;
> +
> +       return ops->route_pmc_gpio_gpe(dev, pmc_gpe_num);
> +}
> +
> +int irq_set_polarity(struct udevice *dev, uint irq, bool active_low)
> +{
> +       const struct irq_ops *ops = irq_get_ops(dev);
> +
> +       if (!ops->set_polarity)
> +               return -ENOSYS;
> +
> +       return ops->set_polarity(dev, irq, active_low);
> +}
> +
> +int irq_snapshot_polarities(struct udevice *dev)
> +{
> +       const struct irq_ops *ops = irq_get_ops(dev);
> +
> +       if (!ops->snapshot_polarities)
> +               return -ENOSYS;
> +
> +       return ops->snapshot_polarities(dev);
> +}
> +
> +int irq_restore_polarities(struct udevice *dev)
> +{
> +       const struct irq_ops *ops = irq_get_ops(dev);
> +
> +       if (!ops->restore_polarities)
> +               return -ENOSYS;
> +
> +       return ops->restore_polarities(dev);
> +}
> +
> +UCLASS_DRIVER(irq) = {
> +       .id             = UCLASS_IRQ,
> +       .name           = "irq",
> +};
> diff --git a/include/irq.h b/include/irq.h
> new file mode 100644
> index 00000000000..01ded64f160
> --- /dev/null
> +++ b/include/irq.h
> @@ -0,0 +1,88 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * IRQ is a type of interrupt controller used on recent Intel SoC.
> + *
> + * Copyright 2019 Google LLC
> + */
> +
> +#ifndef __irq_H
> +#define __irq_H
> +
> +/**
> + * struct irq_ops - Operations for the IRQ
> + */
> +struct irq_ops {
> +       /**
> +        * route_pmc_gpio_gpe() - Get the GPIO for an event
> +        *
> +        * @dev: IRQ device
> +        * @pmc_gpe_num: Event number to check
> +        * @returns GPIO for the event, or -ENOENT if none
> +        */
> +       int (*route_pmc_gpio_gpe)(struct udevice *dev, uint pmc_gpe_num);
> +
> +       /**
> +        * set_polarity() - Set the IRQ polarity
> +        *
> +        * @dev: IRQ device
> +        * @irq: Interrupt number to set
> +        * @active_low: true if active low, false for active high
> +        * @return 0 if OK, -EINVAL if @irq is invalid
> +        */
> +       int (*set_polarity)(struct udevice *dev, uint irq, bool active_low);
> +
> +       /**
> +        * snapshot_polarities() - record IRQ polarities for later restore
> +        *
> +        * @dev: IRQ device
> +        * @return 0
> +        */
> +       int (*snapshot_polarities)(struct udevice *dev);
> +
> +       /**
> +        * restore_polarities() - restore IRQ polarities
> +        *
> +        * @dev: IRQ device
> +        * @return 0
> +        */
> +       int (*restore_polarities)(struct udevice *dev);
> +};
> +
> +#define irq_get_ops(dev)       ((struct irq_ops *)(dev)->driver->ops)
> +
> +/**
> + * irq_route_pmc_gpio_gpe() - Get the GPIO for an event
> + *
> + * @dev: IRQ device
> + * @pmc_gpe_num: Event number to check
> + * @returns GPIO for the event, or -ENOENT if none
> + */
> +int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num);
> +
> +/**
> + * irq_set_polarity() - Set the IRQ polarity
> + *
> + * @dev: IRQ device
> + * @irq: Interrupt number to set
> + * @active_low: true if active low, false for active high
> + * @return 0 if OK, -EINVAL if @irq is invalid
> + */
> +int irq_set_polarity(struct udevice *dev, uint irq, bool active_low);
> +
> +/**
> + * irq_snapshot_polarities() - record IRQ polarities for later restore
> + *
> + * @dev: IRQ device
> + * @return 0
> + */
> +int irq_snapshot_polarities(struct udevice *dev);
> +
> +/**
> + * irq_restore_polarities() - restore IRQ polarities
> + *
> + * @dev: IRQ device
> + * @return 0
> + */
> +int irq_restore_polarities(struct udevice *dev);
> +
> +#endif
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 039/108] sandbox: Add a test for IRQ
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 039/108] sandbox: Add a test for IRQ Simon Glass
@ 2019-11-04  8:45   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:45 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add a simple sandbox test for this uclass.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Change the sandbox test from ITSS to IRQ
>
> Changes in v2: None
>
>  arch/sandbox/dts/test.dts          |  4 +++
>  configs/sandbox_defconfig          |  3 +-
>  configs/sandbox_flattree_defconfig |  1 +
>  configs/sandbox_spl_defconfig      |  1 +
>  drivers/misc/Makefile              |  2 +-
>  drivers/misc/irq_sandbox.c         | 55 ++++++++++++++++++++++++++++++
>  test/dm/Makefile                   |  1 +
>  test/dm/irq.c                      | 32 +++++++++++++++++
>  8 files changed, 97 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/misc/irq_sandbox.c
>  create mode 100644 test/dm/irq.c
>
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index 24631770544..05f26df6a82 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -349,6 +349,10 @@
>                 vss-microvolts = <0>;
>         };
>
> +       irq {
> +               compatible = "sandbox,irq";
> +       };
> +
>         lcd {
>                 u-boot,dm-pre-reloc;
>                 compatible = "sandbox,lcd-sdl";
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index f8b78b8d7e1..fd2cd764e2c 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -130,6 +130,8 @@ CONFIG_CROS_EC_I2C=y
>  CONFIG_CROS_EC_LPC=y
>  CONFIG_CROS_EC_SANDBOX=y
>  CONFIG_CROS_EC_SPI=y
> +CONFIG_IRQ=y
> +CONFIG_P2SB=y
>  CONFIG_PWRSEQ=y
>  CONFIG_SPL_PWRSEQ=y
>  CONFIG_I2C_EEPROM=y
> @@ -150,7 +152,6 @@ CONFIG_PCI=y
>  CONFIG_DM_PCI=y
>  CONFIG_DM_PCI_COMPAT=y
>  CONFIG_PCI_SANDBOX=y
> -CONFIG_P2SB=y

Instead of adjusting P2SB order here, please update previous patch to
insert P2SB to the right place, then this patch should only touch
CONFIG_IRQ.

>  CONFIG_PHY=y
>  CONFIG_PHY_SANDBOX=y
>  CONFIG_PINCTRL=y
> diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
> index 230d65b14a7..d1c18ff96cd 100644
> --- a/configs/sandbox_flattree_defconfig
> +++ b/configs/sandbox_flattree_defconfig
> @@ -98,6 +98,7 @@ CONFIG_CROS_EC_I2C=y
>  CONFIG_CROS_EC_LPC=y
>  CONFIG_CROS_EC_SANDBOX=y
>  CONFIG_CROS_EC_SPI=y
> +CONFIG_IRQ=y
>  CONFIG_PWRSEQ=y
>  CONFIG_SPL_PWRSEQ=y
>  CONFIG_I2C_EEPROM=y
> diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
> index 405b6015474..0f66b2aee0a 100644
> --- a/configs/sandbox_spl_defconfig
> +++ b/configs/sandbox_spl_defconfig
> @@ -118,6 +118,7 @@ CONFIG_CROS_EC_I2C=y
>  CONFIG_CROS_EC_LPC=y
>  CONFIG_CROS_EC_SANDBOX=y
>  CONFIG_CROS_EC_SPI=y
> +CONFIG_IRQ=y
>  CONFIG_PWRSEQ=y
>  CONFIG_SPL_PWRSEQ=y
>  CONFIG_MMC_SANDBOX=y
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 9a0c6f08dec..bd2469f67b0 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -42,10 +42,10 @@ obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
>  obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
>  obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
>  obj-$(CONFIG_IRQ) += irq-uclass.o
> +obj-$(CONFIG_SANDBOX) += irq_sandbox.o
>  obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
>  obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
>  obj-$(CONFIG_IMX8) += imx8/
> -obj-$(CONFIG_ITSS) += itss-uclass.o

This should be dropped in previous patch.

>  obj-$(CONFIG_LED_STATUS) += status_led.o
>  obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
>  obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
> diff --git a/drivers/misc/irq_sandbox.c b/drivers/misc/irq_sandbox.c
> new file mode 100644
> index 00000000000..6dda1a4c442
> --- /dev/null
> +++ b/drivers/misc/irq_sandbox.c
> @@ -0,0 +1,55 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Sandbox driver for interrupts
> + *
> + * Copyright 2019 Google LLC
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <irq.h>
> +
> +static int sandbox_set_polarity(struct udevice *dev, uint irq, bool active_low)
> +{
> +       if (irq > 10)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int sandbox_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
> +{
> +       if (pmc_gpe_num > 10)
> +               return -ENOENT;
> +
> +       return pmc_gpe_num + 1;
> +}
> +
> +static int sandbox_snapshot_polarities(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +static int sandbox_restore_polarities(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +static const struct irq_ops sandbox_irq_ops = {
> +       .route_pmc_gpio_gpe     = sandbox_route_pmc_gpio_gpe,
> +       .set_polarity           = sandbox_set_polarity,
> +       .snapshot_polarities    = sandbox_snapshot_polarities,
> +       .restore_polarities     = sandbox_restore_polarities,
> +};
> +
> +static const struct udevice_id sandbox_irq_ids[] = {
> +       { .compatible = "sandbox,irq"},
> +       { }
> +};
> +
> +U_BOOT_DRIVER(sandbox_irq_drv) = {
> +       .name           = "sandbox_irq",
> +       .id             = UCLASS_IRQ,
> +       .of_match       = sandbox_irq_ids,
> +       .ops            = &sandbox_irq_ops,
> +};
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 129ccb3b496..a2687831696 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_DM_GPIO) += gpio.o
>  obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o
>  obj-$(CONFIG_DM_I2C) += i2c.o
>  obj-$(CONFIG_SOUND) += i2s.o
> +obj-y += irq.o
>  obj-$(CONFIG_LED) += led.o
>  obj-$(CONFIG_DM_MAILBOX) += mailbox.o
>  obj-$(CONFIG_DM_MMC) += mmc.o
> diff --git a/test/dm/irq.c b/test/dm/irq.c
> new file mode 100644
> index 00000000000..726189c59f7
> --- /dev/null
> +++ b/test/dm/irq.c
> @@ -0,0 +1,32 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Test for irq uclass
> + *
> + * Copyright 2019 Google LLC
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <irq.h>
> +#include <dm/test.h>
> +#include <test/ut.h>
> +
> +/* Base test of the irq uclass */
> +static int dm_test_irq_base(struct unit_test_state *uts)
> +{
> +       struct udevice *dev;
> +
> +       ut_assertok(uclass_first_device_err(UCLASS_IRQ, &dev));
> +
> +       ut_asserteq(5, irq_route_pmc_gpio_gpe(dev, 4));
> +       ut_asserteq(-ENOENT, irq_route_pmc_gpio_gpe(dev, 14));
> +
> +       ut_assertok(irq_set_polarity(dev, 4, true));
> +       ut_asserteq(-EINVAL, irq_set_polarity(dev, 14, true));
> +
> +       ut_assertok(irq_snapshot_polarities(dev));
> +       ut_assertok(irq_restore_polarities(dev));
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_irq_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 040/108] x86: Define the SPL image start
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 040/108] x86: Define the SPL image start Simon Glass
@ 2019-11-04  8:46   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:46 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Define this symbol so that we can use binman symbols correctly.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/cpu/u-boot-spl.lds | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 041/108] x86: Reduce mrccache record alignment size
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 041/108] x86: Reduce mrccache record alignment size Simon Glass
@ 2019-11-04  8:50   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04  8:50 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present the records are 4KB in size. This is unnecessarily large when
> the SPI-flash erase size is 256 bytes. Reduce it so it will be more
> efficient with Apollolake's 24-byte variable-data record.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/include/asm/mrccache.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 042/108] x86: Correct mrccache find_next_mrc_cache() calculation
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 042/108] x86: Correct mrccache find_next_mrc_cache() calculation Simon Glass
@ 2019-11-04 15:01   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04 15:01 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> This should take account of the end of the new cache record since a record
> cannot extend beyond the end of the flash region. This problem was not
> seen before due to the alignment of the relatively small amount of MRC
> data.
>
> But with apollolake the MRC data is about 45KB, even if most of it is
> zeroes.
>
> Fix this bug and update the parameter name to be less confusing.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add an extra size parameter to the find_next_mrc_cache() function
>
> Changes in v2: None
>
>  arch/x86/lib/mrccache.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
> index 33bb52039bd..7292d1fe070 100644
> --- a/arch/x86/lib/mrccache.c
> +++ b/arch/x86/lib/mrccache.c
> @@ -80,21 +80,26 @@ struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
>  /**
>   * find_next_mrc_cache() - get next cache entry
>   *
> + * This moves to the next cache entry in the region, making sure it has enough
> + * space to hold data of size @data_size.
> + *
>   * @entry:     MRC cache flash area
>   * @cache:     Entry to start from
> + * @data_size: Required data size of the new entry
>   *
>   * @return next cache entry if found, NULL if we got to the end
>   */
>  static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
> -               struct mrc_data_container *cache)
> +               struct mrc_data_container *prev, int data_size)
>  {
> +       struct mrc_data_container *cache;
>         ulong base_addr, end_addr;
>
>         base_addr = entry->base + entry->offset;
>         end_addr = base_addr + entry->length;
>
> -       cache = next_mrc_block(cache);
> -       if ((ulong)cache >= end_addr) {
> +       cache = next_mrc_block(prev);
> +       if ((ulong)cache + mrc_block_size(prev->data_size) > end_addr) {

It takes me another several minutes to understand this, as I was
confused by the v2 patch :)

So in v2 we agreed to add some comments here, as we assume the
data_size will be the same.

>                 /* Crossed the boundary */
>                 cache = NULL;
>                 debug("%s: no available entries found\n", __func__);
> @@ -131,7 +136,7 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
>
>         /* Move to the next block, which will be the first unused block */
>         if (cache)
> -               cache = find_next_mrc_cache(entry, cache);
> +               cache = find_next_mrc_cache(entry, cache, cur->data_size);
>
>         /*
>          * If we have got to the end, erase the entire mrc-cache area and start
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree Simon Glass
@ 2019-11-04 15:06   ` Bin Meng
  2019-11-12  0:51     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-04 15:06 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Change the algorithm to first find the flash device then read the
> properties using the livetree API. With this change the device is not
> probed so this needs to be done in mrccache_save().
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Update mrccache livetree patch to just convert to livetree
>
> Changes in v2: None
>
>  arch/x86/lib/mrccache.c | 55 +++++++++++++++++++----------------------
>  1 file changed, 26 insertions(+), 29 deletions(-)
>
> diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
> index 7292d1fe070..b8bc5de602c 100644
> --- a/arch/x86/lib/mrccache.c
> +++ b/arch/x86/lib/mrccache.c
> @@ -14,6 +14,8 @@
>  #include <spi.h>
>  #include <spi_flash.h>
>  #include <asm/mrccache.h>
> +#include <dm/device-internal.h>
> +#include <dm/uclass-internal.h>
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> @@ -201,45 +203,37 @@ int mrccache_reserve(void)
>
>  int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
>  {
> -       const void *blob = gd->fdt_blob;
> -       int node, mrc_node;
> +       struct udevice *dev;
> +       ofnode mrc_node;
>         u32 reg[2];
>         int ret;
>
> -       /* Find the flash chip within the SPI controller node */
> -       node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
> -       if (node < 0) {
> -               debug("%s: Cannot find SPI flash\n", __func__);
> -               return -ENOENT;
> -       }
> -
> -       if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) {
> -               debug("%s: Cannot find memory map\n", __func__);
> -               return -EINVAL;
> -       }
> +       /*
> +        * Find the flash chip within the SPI controller node. Avoid probing
> +        * the device here since it may put it into a strange state where the
> +        * memory map cannot be read.
> +        */
> +       ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);

Adding probe of UCLASS_SPI_FLASH should be in the next patch:

[U-Boot,v3,044/108] x86: Adjust mrccache_get_region() to support get_mmap()

> +       if (ret)
> +               return log_msg_ret("Cannot find SPI flash\n", ret);
> +       ret = dev_read_u32_array(dev, "memory-map", reg, 2);
> +       if (ret)
> +               return log_msg_ret("Cannot find memory map\n", ret);
>         entry->base = reg[0];
>
>         /* Find the place where we put the MRC cache */
> -       mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
> -       if (mrc_node < 0) {
> -               debug("%s: Cannot find node\n", __func__);
> -               return -EPERM;
> -       }
> +       mrc_node = dev_read_subnode(dev, "rw-mrc-cache");
> +       if (!ofnode_valid(mrc_node))
> +               return log_msg_ret("Cannot find node", -EPERM);
>
> -       if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) {
> -               debug("%s: Cannot find address\n", __func__);
> -               return -EINVAL;
> -       }
> +       ret = ofnode_read_u32_array(mrc_node, "reg", reg, 2);
> +       if (ret)
> +               return log_msg_ret("Cannot find address", ret);
>         entry->offset = reg[0];
>         entry->length = reg[1];
>
> -       if (devp) {
> -               ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
> -                                                    devp);
> -               debug("ret = %d\n", ret);
> -               if (ret)
> -                       return ret;
> -       }
> +       if (devp)
> +               *devp = dev;
>
>         return 0;
>  }
> @@ -257,6 +251,9 @@ int mrccache_save(void)
>               gd->arch.mrc_output_len);
>
>         ret = mrccache_get_region(&sf, &entry);
> +       if (ret)
> +               goto err_entry;
> +       ret = device_probe(sf);

This needs a comment as we discussed in v2, or maybe it should also go
into next patch?

>         if (ret)
>                 goto err_entry;
>         data  = (struct mrc_data_container *)gd->arch.mrc_output;
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 047/108] x86: Update mrccache to support multiple caches
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 047/108] x86: Update mrccache to support multiple caches Simon Glass
@ 2019-11-04 15:22   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04 15:22 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> With apollolake we need to support a normal cache, which almost never
> changes and a much smaller 'variable' cache which changes every time.
>
> Update the code to add a cache type, use an array for the caches and use a
> for loop to iterate over the caches.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Move line related to variable-cache into the next patch
>
> Changes in v2: None
>
>  arch/x86/cpu/broadwell/sdram.c     |  8 ++-
>  arch/x86/cpu/ivybridge/sdram.c     |  8 ++-
>  arch/x86/cpu/quark/dram.c          |  8 ++-
>  arch/x86/include/asm/global_data.h | 21 +++++--
>  arch/x86/include/asm/mrccache.h    | 11 +++-
>  arch/x86/lib/fsp/fsp_common.c      |  2 +-
>  arch/x86/lib/fsp1/fsp_dram.c       |  8 ++-
>  arch/x86/lib/mrccache.c            | 88 ++++++++++++++++++++----------
>  8 files changed, 106 insertions(+), 48 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 048/108] x86: Add mrccache support for a 'variable' cache
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 048/108] x86: Add mrccache support for a 'variable' cache Simon Glass
@ 2019-11-04 15:23   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04 15:23 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add support for a second cache type, for apollolake.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Move the mrccache_get_region() change into this patch
>
> Changes in v2: None
>
>  arch/x86/include/asm/mrccache.h | 1 +
>  arch/x86/lib/mrccache.c         | 3 ++-
>  2 files changed, 3 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 050/108] x86: Set the DRAM banks to reflect real location
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 050/108] x86: Set the DRAM banks to reflect real location Simon Glass
@ 2019-11-04 15:24   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-04 15:24 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present with fsp a single DRAM bank is added which extends to the
> whole size of memory. However there is typically only 2GB of memory
> available below the 4GB boundary, and this is what is used by U-Boot while
> running in 32-bit mode.
>
> Scan the tables to set the banks correct. The first bank is set to memory
> below 4GB, and the rest of memory is put into subsequent banks.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Move mtrr_add_request() call to next patch
>
> Changes in v2: None
>
>  arch/x86/lib/fsp/fsp_dram.c | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree
  2019-11-04 15:06   ` Bin Meng
@ 2019-11-12  0:51     ` Simon Glass
  2019-11-13 15:16       ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-11-12  0:51 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Mon, 4 Nov 2019 at 08:06, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Change the algorithm to first find the flash device then read the
> > properties using the livetree API. With this change the device is not
> > probed so this needs to be done in mrccache_save().
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > - Update mrccache livetree patch to just convert to livetree
> >
> > Changes in v2: None
> >
> >  arch/x86/lib/mrccache.c | 55 +++++++++++++++++++----------------------
> >  1 file changed, 26 insertions(+), 29 deletions(-)

Just checking if I should send a new series with all these comments,
or still hold off?

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree
  2019-11-12  0:51     ` Simon Glass
@ 2019-11-13 15:16       ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-13 15:16 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Tue, Nov 12, 2019 at 8:51 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Mon, 4 Nov 2019 at 08:06, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Change the algorithm to first find the flash device then read the
> > > properties using the livetree API. With this change the device is not
> > > probed so this needs to be done in mrccache_save().
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > ---
> > >
> > > Changes in v3:
> > > - Update mrccache livetree patch to just convert to livetree
> > >
> > > Changes in v2: None
> > >
> > >  arch/x86/lib/mrccache.c | 55 +++++++++++++++++++----------------------
> > >  1 file changed, 26 insertions(+), 29 deletions(-)
>
> Just checking if I should send a new series with all these comments,
> or still hold off?

Sorry I was on travel for the past days and am still traveling. I will
be looking the remaining patches during this weekend.

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 051/108] x86: Set up the MTRR for SDRAM
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 051/108] x86: Set up the MTRR for SDRAM Simon Glass
@ 2019-11-19  2:23   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  2:23 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Set up MTRRs for the FST SDRAM regions to improve performance.

typo: FST -> FSP

>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Move mtrr_add_request() call into this patch
>
> Changes in v2: None
>
>  arch/x86/lib/fsp/fsp_dram.c | 5 +++++
>  1 file changed, 5 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 052/108] x86: Don't imply libfdt or SPI flash in TPL
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 052/108] x86: Don't imply libfdt or SPI flash in TPL Simon Glass
@ 2019-11-19  2:23   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  2:23 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> We don't want to pull in libfdt if of-platdata is being used, since it
> reduces the available code-size saves. Also, SPI flash is seldom needed
> in TPL.
>
> Drop these options.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Don't imply SPI flash either
> - Rewrite commit message
>
> Changes in v2: None
>
>  arch/Kconfig | 3 ---
>  1 file changed, 3 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 055/108] x86: fsp: Make graphics support common to FSP1/2
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 055/108] x86: fsp: Make graphics support common to FSP1/2 Simon Glass
@ 2019-11-19  2:23   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  2:23 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Both versions of FSP can use the same graphics support, so move it into
> the common directory.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/lib/fsp/Makefile                 | 3 +++
>  arch/x86/lib/{fsp1 => fsp}/fsp_graphics.c | 2 +-
>  arch/x86/lib/fsp1/Makefile                | 1 -
>  3 files changed, 4 insertions(+), 2 deletions(-)
>  rename arch/x86/lib/{fsp1 => fsp}/fsp_graphics.c (98%)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 056/108] x86: fsp: Correct wrong header inlude in fsp_support.c
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 056/108] x86: fsp: Correct wrong header inlude in fsp_support.c Simon Glass
@ 2019-11-19  7:25   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  7:25 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> This generic FSP file should include the generic FSP support header, not
> the FSP1 version. Fix it.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/lib/fsp/fsp_support.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support Simon Glass
@ 2019-11-19  7:25   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19  7:25 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add support for some important configuration options and FSP memory init.
> The memory init uses swizzle tables from the device tree.
>
> Support for the FSP_S binary is also included.
>
> Bootstage timing is used for both FSP_M and FSP_M and memory-mapped SPI

FSP_T and FSP_M ?

> reads.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add a proper implementation of fsp_notify
> - Add an fsp: tag
> - Add bootstage timing for memory-mapped reads
> - Add fsp_locate_fsp to locate an fsp component
> - Add fspm_done() hook
> - Add support for FSP-S component and VBT
> - Simplify types for fsp_locate_fsp()
> - Switch mmap to use SPI instead of SPI flash
>
> Changes in v2: None
>
>  arch/x86/Kconfig                         |  61 ++++++++-
>  arch/x86/include/asm/fsp2/fsp_api.h      |  60 +++++++++
>  arch/x86/include/asm/fsp2/fsp_internal.h |  97 ++++++++++++++
>  arch/x86/lib/fsp2/Makefile               |  10 ++
>  arch/x86/lib/fsp2/fsp_common.c           |  13 ++
>  arch/x86/lib/fsp2/fsp_dram.c             |  77 +++++++++++
>  arch/x86/lib/fsp2/fsp_init.c             | 157 +++++++++++++++++++++++
>  arch/x86/lib/fsp2/fsp_meminit.c          |  97 ++++++++++++++
>  arch/x86/lib/fsp2/fsp_silicon_init.c     |  52 ++++++++
>  arch/x86/lib/fsp2/fsp_support.c          | 129 +++++++++++++++++++
>  include/bootstage.h                      |   3 +
>  11 files changed, 754 insertions(+), 2 deletions(-)
>  create mode 100644 arch/x86/include/asm/fsp2/fsp_api.h
>  create mode 100644 arch/x86/include/asm/fsp2/fsp_internal.h
>  create mode 100644 arch/x86/lib/fsp2/Makefile
>  create mode 100644 arch/x86/lib/fsp2/fsp_common.c
>  create mode 100644 arch/x86/lib/fsp2/fsp_dram.c
>  create mode 100644 arch/x86/lib/fsp2/fsp_init.c
>  create mode 100644 arch/x86/lib/fsp2/fsp_meminit.c
>  create mode 100644 arch/x86/lib/fsp2/fsp_silicon_init.c
>  create mode 100644 arch/x86/lib/fsp2/fsp_support.c
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 17a6fe6d3d9..cbd3fc4f581 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -326,7 +326,7 @@ config X86_RAMTEST
>
>  config FLASH_DESCRIPTOR_FILE
>         string "Flash descriptor binary filename"
> -       depends on HAVE_INTEL_ME
> +       depends on HAVE_INTEL_ME || FSP_VERSION2
>         default "descriptor.bin"
>         help
>           The filename of the file to use as flash descriptor in the
> @@ -411,6 +411,63 @@ config FSP_ADDR
>           The default base address of 0xfffc0000 indicates that the binary must
>           be located at offset 0xc0000 from the beginning of a 1MB flash device.
>
> +if FSP_VERSION2
> +
> +config FSP_FILE_T
> +       string "Firmware-Support-Package binary filename (Temp RAM)"
> +       default "fsp_t.bin"
> +       help
> +         The filename of the file to use for the temporary-RAM init phase from
> +         the Firmware-Support-Package binary. Put this in the board directory.
> +         It is used to set up an initial area of RAM which can be used for the
> +         stack and other purposes, while bringing up the main system DRAM.
> +
> +config FSP_ADDR_T
> +       hex "Firmware-Support-Package binary location (Temp RAM)"
> +       default 0xffff8000
> +       help
> +         FSP is not Position-Independent Code (PIC) and FSP components have to
> +         be rebased if placed at a location which is different from the
> +         perferred base address specified during the FSP build. Use Intel's
> +         Binary Configuration Tool (BCT) to do the rebase.
> +
> +config FSP_FILE_M
> +       string "Firmware-Support-Package binary filename (Memory Init)"
> +       default "fsp_m.bin"
> +       help
> +         The filename of the file to use for the RAM init phase from the
> +         Firmware Support Package binary. Put this in the board directory.
> +         It is used to set up the main system DRAM and runs in SPL, once
> +         temporary RAM (CAR) is working.
> +
> +config FSP_FILE_S
> +       string "Firmware-Support-Package binary filename (Silicon Init)"
> +       default "fsp_s.bin"
> +       help
> +         The filename of the file to use for the Silicon init phase from the
> +         Firmware Support Package binary. Put this in the board directory.
> +         It is used to set up the silicon to work correctly and must be
> +         executed after DRAM is running.
> +
> +config FSP_FILE_VBT

There is already a VBT_FILE config option for this.

> +       string "Firmware-Support-Package Video BIOS Table (VBT)"
> +       default "vbt.bin"
> +       help
> +         The filename of the file to use for the video data needd by the
> +         Silicon init phase from the Firmware Support Package binary. Put this
> +         in the board directory. It is used to set up the video parameters so
> +         that the display can be used.
> +
> +config IFWI_INPUT_FILE
> +       string "Filename containing FIT (Firmware Interface Table) with IFWI"
> +       default "fitimage.bin"
> +       help
> +         The IFWI is obtained by running a tool on this file to extract the
> +         IFWI. Put this in the board directory. The IFWI contains U-Boot TPL,
> +         microcode and other internal items.
> +
> +endif
> +
>  config FSP_TEMP_RAM_ADDR
>         hex
>         depends on FSP_VERSION1
> @@ -629,7 +686,7 @@ config VBT_ADDR
>
>  config VIDEO_FSP
>         bool "Enable FSP framebuffer driver support"
> -       depends on HAVE_VBT && DM_VIDEO
> +       depends on (HAVE_VBT || FSP_VERSION2) && DM_VIDEO
>         help
>           Turn on this option to enable a framebuffer driver when U-Boot is
>           using Video BIOS Table (VBT) image for FSP firmware to initialize
> diff --git a/arch/x86/include/asm/fsp2/fsp_api.h b/arch/x86/include/asm/fsp2/fsp_api.h
> new file mode 100644
> index 00000000000..93b6472dce0
> --- /dev/null
> +++ b/arch/x86/include/asm/fsp2/fsp_api.h
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: Intel */
> +/*
> + * Copyright (C) 2015-2016 Intel Corp.
> + * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
> + * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
> + * Mostly taken from coreboot fsp2_0/memory_init.c
> + */
> +
> +#ifndef __ASM_FSP2_API_H
> +#define __ASM_FSP2_API_H
> +
> +#include <asm/fsp/fsp_api.h>
> +
> +struct fspm_upd;
> +struct fsps_upd;
> +struct hob_header;
> +
> +enum fsp_boot_mode {
> +       FSP_BOOT_WITH_FULL_CONFIGURATION = 0x00,
> +       FSP_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01,
> +       FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02,
> +       FSP_BOOT_ON_S4_RESUME = 0x05,
> +       FSP_BOOT_ON_S3_RESUME = 0x11,
> +       FSP_BOOT_ON_FLASH_UPDATE = 0x12,
> +       FSP_BOOT_IN_RECOVERY_MODE = 0x20
> +};
> +
> +struct __packed fsp_upd_header {
> +       u64     signature;
> +       u8      revision;
> +       u8      reserved[23];
> +};
> +
> +/**
> + * fsp_memory_init() - Init the SDRAM
> + *
> + * @s3wake: true if we are booting from resume, so cannot reinit the mememory
> + *     from scatch since we will lose its contents
> + * @use_spi_flash: true to use the fast SPI driver to read FSP, otherwise use
> + *     mapped SPI
> + * @return 0 if OK, -ve on error
> + */
> +int fsp_memory_init(bool s3wake, bool use_spi_flash);
> +
> +typedef asmlinkage int (*fsp_memory_init_func)(struct fspm_upd *params,
> +                                              struct hob_header **hobp);
> +
> +/**
> + * fsp_silicon_init() - Init the silicon
> + *
> + * This calls the FSP's 'silicon init' entry point
> + *
> + * @s3wake: true if we are booting from resume

Should have the same descriptions as fsp_memory_init()

> + * @return 0 if OK, -ve on error
> + */
> +int fsp_silicon_init(bool s3wake, bool use_spi_flash);
> +
> +typedef asmlinkage int (*fsp_silicon_init_func)(struct fsps_upd *params);
> +
> +#endif
> diff --git a/arch/x86/include/asm/fsp2/fsp_internal.h b/arch/x86/include/asm/fsp2/fsp_internal.h
> new file mode 100644
> index 00000000000..5893f1ffcc7
> --- /dev/null
> +++ b/arch/x86/include/asm/fsp2/fsp_internal.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: Intel */
> +/*
> + * Copyright (C) 2015-2016 Intel Corp.
> + * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
> + * Mostly taken from coreboot
> + */
> +
> +#ifndef __ASM_FSP_INTERNAL_H
> +#define __ASM_FSP_INTERNAL_H
> +
> +struct binman_entry;
> +struct fsp_header;
> +struct fspm_upd;
> +struct fsps_upd;
> +
> +enum fsp_type_t {
> +       FSP_M,
> +       FSP_S,
> +};
> +
> +int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
> +                  struct fsp_header **fspp);
> +
> +/**
> + * fsp_locate_fsp() - Locate an FSP component
> + *
> + * This finds an FSP component by various methods. It is not as general-purpose
> + * as it looks, since it expects FSP-M to be requested in SPL (only), and FSP-S
> + * to be requested in U-Boot proper.
> + *
> + * @type: Component to locate
> + * @entry: Returns location of component
> + * @use_spi_flash: true to read using the Fast SPI driver, false to use
> + *     memory-mapped SPI flash
> + * @devp: Returns northbridge device
> + * @hdrp: Returns FSP header
> + * @rom_offsetp: If non-NULL, returns the offset to add to any image position to
> + *     find the memory-mapped location of that position. For example, for ROM
> + *     position 0x1000, it will be mapped into 0x1000 + *rom_offsetp.
> + */
> +int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
> +                  bool use_spi_flash, struct udevice **devp,
> +                  struct fsp_header **hdrp, ulong *rom_offsetp);
> +
> +/**
> + * arch_fsp_s_preinit() - Perform init needed before calling FSP-S

Considering other routines in this file are having fspm_ as the
prefix, should we name this function to arch_fsps_preinit()?

Or rename others to fsp_m_ as the prefix?

> + *
> + * This allows use of probed drivers and PCI so is a convenient place to do any
> + * init that is needed before FSP-S is called. After this, U-Boot relocates and
> + * calls arch_fsp_init_r() before PCI is probed, and that function is not
> + * allowed to probe PCI before calling FSP-S.
> + */
> +int arch_fsp_s_preinit(void);
> +
> +/**
> + * fspm_update_config() - Set up the config structure for FSP-M
> + *
> + * @dev: Hostbridge device containing config
> + * @upd: Config data to fill in
> + * @return 0 if OK, -ve on error
> + */
> +int fspm_update_config(struct udevice *dev, struct fspm_upd *upd);
> +
> +/**
> + * fspm_done() - Indicate that memory init is complete
> + *
> + * This allows the board to do whatever post-init it needs before things
> + * continue.
> + *
> + * @dev: Hostbridge device
> + * @return 0 if OK, -ve on error
> + */
> +int fspm_done(struct udevice *dev);
> +
> +/**
> + * fsps_update_config() - Set up the config structure for FSP-S
> + *
> + * @dev: Hostbridge device containing config
> + * @rom_offset: Value to add to convert from ROM offset to memory-mapped address
> + * @upd: Config data to fill in
> + * @return 0 if OK, -ve on error
> + */
> +int fsps_update_config(struct udevice *dev, ulong rom_offset,
> +                      struct fsps_upd *upd);
> +
> +/**
> + * prepare_mrc_cache() - Read the MRC cache into the product-data struct
> + *
> + * This looks for cached Memory-reference code (MRC) data and stores it into
> + * @upd for use by the FSP-M binary.
> + *
> + * @return 0 if OK, -ENOENT if no data (whereupon the caller can continue and
> + *     expect a slower boot), other -ve value on other error
> + */
> +int prepare_mrc_cache(struct fspm_upd *upd);
> +
> +#endif
> diff --git a/arch/x86/lib/fsp2/Makefile b/arch/x86/lib/fsp2/Makefile
> new file mode 100644
> index 00000000000..ddbe2d0db26
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/Makefile
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright 2019 Google LLC
> +
> +obj-y += fsp_common.o
> +obj-y += fsp_dram.o
> +obj-y += fsp_init.o
> +obj-y += fsp_meminit.o
> +obj-y += fsp_silicon_init.o
> +obj-y += fsp_support.o
> diff --git a/arch/x86/lib/fsp2/fsp_common.c b/arch/x86/lib/fsp2/fsp_common.c
> new file mode 100644
> index 00000000000..f69456e43a2
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/fsp_common.c
> @@ -0,0 +1,13 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +
> +int arch_fsp_init(void)
> +{
> +       return 0;
> +}
> diff --git a/arch/x86/lib/fsp2/fsp_dram.c b/arch/x86/lib/fsp2/fsp_dram.c
> new file mode 100644
> index 00000000000..a3f95d0cf96
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/fsp_dram.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#include <common.h>
> +#include <acpi_s3.h>
> +#include <handoff.h>
> +#include <spl.h>
> +#include <asm/arch/cpu.h>
> +#include <asm/fsp/fsp_support.h>
> +#include <asm/fsp2/fsp_api.h>
> +#include <asm/fsp2/fsp_internal.h>
> +
> +int dram_init(void)
> +{
> +       int ret;
> +
> +       if (spl_phase() == PHASE_SPL) {
> +#ifdef CONFIG_HAVE_ACPI_RESUME
> +               bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
> +#else
> +               bool s3wake = false;
> +#endif
> +
> +               ret = fsp_memory_init(s3wake, BOOT_FROM_FAST_SPI_FLASH);
> +               if (ret) {
> +                       debug("Memory init failed (err=%x)\n", ret);
> +                       return ret;
> +               }
> +
> +               /* The FSP has already set up DRAM, so grab the info we need */
> +               ret = fsp_scan_for_ram_size();
> +               if (ret)
> +                       return ret;
> +
> +#ifdef CONFIG_ENABLE_MRC_CACHE
> +               gd->arch.mrc[MRC_TYPE_NORMAL].buf =
> +                       fsp_get_nvs_data(gd->arch.hob_list,
> +                                        &gd->arch.mrc[MRC_TYPE_NORMAL].len);
> +               gd->arch.mrc[MRC_TYPE_VAR].buf =
> +                       fsp_get_var_nvs_data(gd->arch.hob_list,
> +                                            &gd->arch.mrc[MRC_TYPE_VAR].len);
> +               log_debug("normal %x, var %x\n",
> +                         gd->arch.mrc[MRC_TYPE_NORMAL].len,
> +                         gd->arch.mrc[MRC_TYPE_VAR].len);
> +#endif
> +       } else {
> +#if CONFIG_IS_ENABLED(HANDOFF)
> +               struct spl_handoff *ho = gd->spl_handoff;
> +
> +               if (!ho) {
> +                       debug("No SPL handoff found\n");
> +                       return -ESTRPIPE;
> +               }
> +               gd->ram_size = ho->ram_size;
> +               handoff_load_dram_banks(ho);
> +#endif
> +               ret = arch_fsp_s_preinit();
> +               if (ret)
> +                       return log_msg_ret("fsp_s_preinit", ret);
> +       }
> +
> +       return 0;
> +}
> +
> +ulong board_get_usable_ram_top(ulong total_size)
> +{
> +#if CONFIG_IS_ENABLED(HANDOFF)
> +       struct spl_handoff *ho = gd->spl_handoff;
> +
> +       return ho->arch.usable_ram_top;
> +#endif
> +
> +       return gd->ram_top;
> +}
> diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c
> new file mode 100644
> index 00000000000..111eb51d34b
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/fsp_init.c
> @@ -0,0 +1,157 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 Google LLC
> + */
> +
> +#include <common.h>
> +#include <binman.h>
> +#include <binman_sym.h>
> +#include <cbfs.h>
> +#include <dm.h>
> +#include <init.h>
> +#include <spi.h>
> +#include <spl.h>
> +#include <spi_flash.h>
> +#include <asm/arch/gpio.h>
> +#include <dm/uclass-internal.h>
> +#include <asm/fsp2/fsp_internal.h>
> +
> +int arch_cpu_init_dm(void)
> +{
> +       struct udevice *dev;
> +       ofnode node;
> +       int ret;
> +
> +       if (spl_phase() != PHASE_BOARD_F)
> +               return 0;
> +
> +       /* Probe all GPIO devices to set up the pads */
> +       ret = uclass_first_device_err(UCLASS_GPIO, &dev);

Why is this GPIO probe needed in the generic FSP support?


> +       if (ret)
> +               return log_msg_ret("no fsp GPIO", ret);
> +       node = ofnode_path("fsp");
> +       if (!ofnode_valid(node))
> +               return log_msg_ret("no fsp params", -EINVAL);
> +       ret = hostbridge_config_pads_for_node(dev, node);
> +       if (ret)
> +               return log_msg_ret("pad config", ret);
> +
> +       return ret;
> +}
> +
> +#if !defined(CONFIG_TPL_BUILD)
> +binman_sym_declare(ulong, intel_fsp_m, image_pos);
> +binman_sym_declare(ulong, intel_fsp_m, size);
> +
> +static int get_coreboot_fsp(enum fsp_type_t type, ulong map_base,

get_uboot_fsp?

> +                           struct binman_entry *entry)
> +{
> +       /* Hard-coded position of CBFS in ROM */

Why hard-coded?

> +       ulong cbfs_base = 0x205000;
> +       ulong cbfs_size = 0x1bb000;
> +       struct cbfs_priv *cbfs;
> +       int ret;
> +
> +       ret = cbfs_init_mem(map_base + cbfs_base, cbfs_size, &cbfs);
> +       if (ret)
> +               return ret;
> +       if (!ret) {
> +               const struct cbfs_cachenode *node;
> +
> +               node = cbfs_find_file(cbfs, "fspm.bin");
> +               if (!node)
> +                       return log_msg_ret("fspm node", -ENOENT);
> +
> +               entry->image_pos = (ulong)node->data;
> +               entry->size = node->data_length;
> +       }
> +
> +       return 0;
> +}
> +
> +int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
> +                  bool use_spi_flash, struct udevice **devp,
> +                  struct fsp_header **hdrp, ulong *rom_offsetp)
> +{
> +       ulong mask = CONFIG_ROM_SIZE - 1;
> +       struct udevice *dev;
> +       ulong rom_offset = 0;
> +       uint map_size;
> +       ulong map_base;
> +       uint offset;
> +       int ret;
> +
> +       /*
> +        * Find the devices but don't probe them, since we don't want to
> +        * auto-config PCI before silicon init runs
> +        */
> +       ret = uclass_find_first_device(UCLASS_NORTHBRIDGE, &dev);
> +       if (ret)
> +               return log_msg_ret("Cannot get northbridge", ret);
> +       if (!use_spi_flash) {
> +               struct udevice *sf;
> +
> +               /* Just use the SPI driver to get the memory map */
> +               ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf);
> +               if (ret)
> +                       return log_msg_ret("Cannot get SPI flash", ret);
> +               ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset);
> +               if (ret)
> +                       return log_msg_ret("Could not get flash mmap", ret);
> +       }
> +
> +       if (spl_phase() >= PHASE_BOARD_F) {
> +               if (type != FSP_S)
> +                       return -EPROTONOSUPPORT;
> +               ret = binman_entry_find("intel-fsp-s", entry);
> +               if (ret)
> +                       return log_msg_ret("binman entry", ret);
> +               if (!use_spi_flash)
> +                       rom_offset = (map_base & mask) - CONFIG_ROM_SIZE;
> +       } else {
> +               ret = -ENOENT;
> +               if (false)
> +                       /* Support using a hybrid image build by coreboot */

U-Boot?

> +                       ret = get_coreboot_fsp(type, map_base, entry);
> +               if (ret) {
> +                       ulong mask = CONFIG_ROM_SIZE - 1;
> +
> +                       if (type != FSP_M)
> +                               return -EPROTONOSUPPORT;
> +                       entry->image_pos = binman_sym(ulong, intel_fsp_m,
> +                                                     image_pos);
> +                       entry->size = binman_sym(ulong, intel_fsp_m, size);
> +                       if (entry->image_pos != BINMAN_SYM_MISSING) {
> +                               ret = 0;
> +                               if (use_spi_flash)
> +                                       entry->image_pos &= mask;
> +                               else
> +                                       entry->image_pos += (map_base & mask);
> +                       } else {
> +                               ret = -ENOENT;
> +                       }
> +               }
> +       }
> +       if (ret)
> +               return log_msg_ret("Cannot find FSP", ret);
> +       entry->image_pos += rom_offset;
> +
> +       /*
> +        * Account for the time taken to read memory-mapped SPI flash since in
> +        * this case we don't use the SPI driver and BOOTSTAGE_ID_ACCUM_SPI.
> +        */
> +       if (!use_spi_flash)
> +               bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
> +       ret = fsp_get_header(entry->image_pos, entry->size, use_spi_flash,
> +                            hdrp);
> +       if (!use_spi_flash)
> +               bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
> +       if (ret)
> +               return log_msg_ret("fsp_get_header", ret);
> +       *devp = dev;
> +       if (rom_offsetp)
> +               *rom_offsetp = rom_offset;
> +
> +       return 0;
> +}
> +#endif
> diff --git a/arch/x86/lib/fsp2/fsp_meminit.c b/arch/x86/lib/fsp2/fsp_meminit.c
> new file mode 100644
> index 00000000000..bf30c479899
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/fsp_meminit.c
> @@ -0,0 +1,97 @@
> +// SPDX-License-Identifier: Intel
> +/*
> + * Copyright (C) 2015-2016 Intel Corp.
> + * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
> + * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
> + * Mostly taken from coreboot fsp2_0/memory_init.c
> + */
> +
> +#include <common.h>
> +#include <binman.h>
> +#include <asm/mrccache.h>
> +#include <asm/fsp/fsp_infoheader.h>
> +#include <asm/fsp2/fsp_api.h>
> +#include <asm/fsp2/fsp_internal.h>
> +#include <asm/arch/fsp/fsp_configs.h>
> +#include <asm/arch/fsp/fsp_m_upd.h>
> +
> +static int prepare_mrc_cache_type(enum mrc_type_t type,
> +                                 struct mrc_data_container **cachep)
> +{
> +       struct mrc_data_container *cache;
> +       struct mrc_region entry;
> +       int ret;
> +
> +       ret = mrccache_get_region(type, NULL, &entry);
> +       if (ret)
> +               return ret;
> +       cache = mrccache_find_current(&entry);
> +       if (!cache)
> +               return -ENOENT;
> +
> +       log_debug("MRC at %x, size %x\n", (uint)cache->data, cache->data_size);
> +       *cachep = cache;
> +
> +       return 0;
> +}
> +
> +int prepare_mrc_cache(struct fspm_upd *upd)
> +{
> +       struct mrc_data_container *cache;
> +       int ret;
> +
> +       ret = prepare_mrc_cache_type(MRC_TYPE_NORMAL, &cache);
> +       if (ret)
> +               return log_msg_ret("Cannot get normal cache", ret);
> +       upd->arch.nvs_buffer_ptr = cache->data;
> +
> +       ret = prepare_mrc_cache_type(MRC_TYPE_VAR, &cache);
> +       if (ret)
> +               return log_msg_ret("Cannot get var cache", ret);
> +       upd->config.variable_nvs_buffer_ptr = cache->data;
> +
> +       return 0;
> +}
> +
> +int fsp_memory_init(bool s3wake, bool use_spi_flash)
> +{
> +       struct fspm_upd upd, *fsp_upd;
> +       fsp_memory_init_func func;
> +       struct binman_entry entry;
> +       struct fsp_header *hdr;
> +       struct hob_header *hob;
> +       struct udevice *dev;
> +       int ret;
> +
> +       ret = fsp_locate_fsp(FSP_M, &entry, use_spi_flash, &dev, &hdr, NULL);
> +       if (ret)
> +               return log_msg_ret("locate FSP", ret);
> +       debug("Found FSP_M at %x, size %x\n", hdr->img_base, hdr->img_size);
> +
> +       /* Copy over the default config */
> +       fsp_upd = (struct fspm_upd *)(hdr->img_base + hdr->cfg_region_off);
> +       if (fsp_upd->header.signature != FSPM_UPD_SIGNATURE)
> +               return log_msg_ret("Bad UPD signature", -EPERM);
> +       memcpy(&upd, fsp_upd, sizeof(upd));
> +
> +       ret = fspm_update_config(dev, &upd);
> +       if (ret)
> +               return log_msg_ret("Could not setup config", ret);
> +
> +       debug("SDRAM init...");
> +       bootstage_start(BOOTSTATE_ID_ACCUM_FSP_M, "fsp-m");
> +       func = (fsp_memory_init_func)(hdr->img_base + hdr->fsp_mem_init);
> +       ret = func(&upd, &hob);
> +       bootstage_accum(BOOTSTATE_ID_ACCUM_FSP_M);
> +       if (ret)
> +               return log_msg_ret("SDRAM init fail\n", ret);
> +
> +       gd->arch.hob_list = hob;
> +       debug("done\n");
> +
> +       ret = fspm_done(dev);
> +       if (ret)
> +               return log_msg_ret("fsm_done\n", ret);
> +
> +       return 0;
> +}
> diff --git a/arch/x86/lib/fsp2/fsp_silicon_init.c b/arch/x86/lib/fsp2/fsp_silicon_init.c
> new file mode 100644
> index 00000000000..c758e80c383
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/fsp_silicon_init.c
> @@ -0,0 +1,52 @@
> +// SPDX-License-Identifier: Intel
> +/*
> + * Copyright (C) 2015-2016 Intel Corp.
> + * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
> + *
> + * Mostly taken from coreboot fsp2_0/silicon_init.c
> + */
> +
> +#include <common.h>
> +#include <binman.h>
> +#include <dm.h>
> +#include <asm/arch/fsp/fsp_configs.h>
> +#include <asm/arch/fsp/fsp_s_upd.h>
> +#include <asm/fsp/fsp_infoheader.h>
> +#include <asm/fsp2/fsp_internal.h>
> +
> +int fsp_silicon_init(bool s3wake, bool use_spi_flash)
> +{
> +       struct fsps_upd upd, *fsp_upd;
> +       fsp_silicon_init_func func;
> +       struct fsp_header *hdr;
> +       struct binman_entry entry;
> +       struct udevice *dev;
> +       ulong rom_offset = 0;
> +       int ret;
> +
> +       ret = fsp_locate_fsp(FSP_S, &entry, use_spi_flash, &dev, &hdr,
> +                            &rom_offset);
> +       if (ret)
> +               return log_msg_ret("locate FSP", ret);
> +       gd->arch.fsp_s_hdr = hdr;
> +
> +       /* Copy over the default config */
> +       fsp_upd = (struct fsps_upd *)(hdr->img_base + hdr->cfg_region_off);
> +       if (fsp_upd->header.signature != FSPS_UPD_SIGNATURE)
> +               return log_msg_ret("Bad UPD signature", -EPERM);
> +       memcpy(&upd, fsp_upd, sizeof(upd));
> +
> +       ret = fsps_update_config(dev, rom_offset, &upd);
> +       if (ret)
> +               return log_msg_ret("Could not setup config", ret);
> +       log_debug("Silicon init...");
> +       bootstage_start(BOOTSTATE_ID_ACCUM_FSP_S, "fsp-s");
> +       func = (fsp_silicon_init_func)(hdr->img_base + hdr->fsp_silicon_init);
> +       ret = func(&upd);
> +       bootstage_accum(BOOTSTATE_ID_ACCUM_FSP_S);
> +       if (ret)
> +               return log_msg_ret("Silicon init fail\n", ret);
> +       log_debug("done\n");
> +
> +       return 0;
> +}
> diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c
> new file mode 100644
> index 00000000000..477eaa268db
> --- /dev/null
> +++ b/arch/x86/lib/fsp2/fsp_support.c
> @@ -0,0 +1,129 @@
> +// SPDX-License-Identifier: Intel
> +/*
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <spi_flash.h>
> +#include <asm/fsp/fsp_support.h>
> +#include <asm/fsp2/fsp_internal.h>
> +
> +/* The amount of the FSP header to probe to obtain what we need */
> +#define PROBE_BUF_SIZE 0x180
> +
> +/* Not needed in SPL apparently */
> +#define SAFETY_MARGIN  0
> +
> +int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
> +                  struct fsp_header **fspp)
> +{
> +       static efi_guid_t guid = FSP_HEADER_GUID;
> +       struct fv_ext_header *exhdr;
> +       struct fsp_header *fsp;
> +       struct ffs_file_header *file_hdr;
> +       struct fv_header *fv;
> +       struct raw_section *raw;
> +       void *ptr, *base;
> +       u8 buf[PROBE_BUF_SIZE];
> +       struct udevice *dev;
> +       int ret;
> +
> +       /* You are in a maze of twisty headers all alike */

What does this comment mean?

> +       debug("offset=%x buf=%x\n", (uint)offset, (uint)buf);
> +       if (use_spi_flash) {
> +               ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
> +               if (ret)
> +                       return log_msg_ret("Cannot find flash device", ret);
> +               ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
> +               if (ret)
> +                       return log_msg_ret("Cannot read flash", ret);
> +       } else {
> +               memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
> +       }
> +
> +       /* Initalise the FSP base */
> +       ptr = buf;
> +       fv = ptr;
> +
> +       /* Check the FV signature, _FVH */
> +       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);
> +       ptr += fv->ext_hdr_off;
> +       exhdr = ptr;
> +       ptr += ALIGN(exhdr->ext_hdr_size, 8);
> +       debug("ptr=%x\n", ptr - (void *)buf);
> +
> +       /* Check the FFS GUID */
> +       file_hdr = ptr;
> +       if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
> +               return log_msg_ret("Base FFS GUID", -ENXIO);
> +       /* Add the FFS header size to find the raw section header */
> +       ptr = file_hdr + 1;
> +
> +       raw = ptr;
> +       debug("raw->type = %x\n", raw->type);
> +       if (raw->type != EFI_SECTION_RAW)
> +               return log_msg_ret("Section type not RAW", -ENOEXEC);
> +
> +       /* Add the raw section header size to find the FSP header */
> +       ptr = raw + 1;
> +       fsp = ptr;
> +
> +       /* Check the FSPH header */
> +       debug("fsp %x\n", (uint)fsp);
> +       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);
> +       if (use_spi_flash) {
> +               ret = spi_flash_read_dm(dev, offset, size + SAFETY_MARGIN,
> +                                       base);
> +               if (ret)
> +                       return log_msg_ret("Could not read FPS-M", ret);
> +       } else {
> +               memcpy(base, (void *)offset, size + SAFETY_MARGIN);
> +       }
> +       ptr = base + (ptr - (void *)buf);
> +       *fspp = ptr;
> +
> +       return 0;
> +}
> +
> +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
> +{
> +       fsp_notify_f notify;
> +       struct fsp_notify_params params;
> +       struct fsp_notify_params *params_ptr;
> +       u32 status;
> +
> +       if (!fsp_hdr)
> +               fsp_hdr = gd->arch.fsp_s_hdr;
> +
> +       if (!fsp_hdr)
> +               return log_msg_ret("no FSP", -ENOENT);
> +
> +       notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
> +       params.phase = phase;
> +       params_ptr = &params;
> +
> +       /*
> +        * Use ASM code to ensure correct parameter is on the stack for
> +        * FspNotify as U-Boot is using different ABI from FSP
> +        */
> +       asm volatile (
> +               "pushl  %1;"            /* push notify phase */
> +               "call   *%%eax;"        /* call FspNotify */
> +               "addl   $4, %%esp;"     /* clean up the stack */
> +               : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
> +       );
> +
> +       return status;
> +}
> diff --git a/include/bootstage.h b/include/bootstage.h
> index 5e7e242b834..c271d3a6cc8 100644
> --- a/include/bootstage.h
> +++ b/include/bootstage.h
> @@ -200,6 +200,9 @@ enum bootstage_id {
>         BOOTSTATE_ID_ACCUM_DM_SPL,
>         BOOTSTATE_ID_ACCUM_DM_F,
>         BOOTSTATE_ID_ACCUM_DM_R,
> +       BOOTSTATE_ID_ACCUM_FSP_M,
> +       BOOTSTATE_ID_ACCUM_FSP_S,
> +       BOOTSTAGE_ID_ACCUM_MMAP_SPI,
>
>         /* a few spare for the user, from here */
>         BOOTSTAGE_ID_USER,
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 058/108] x86: fsp: Set up an MTRR for the graphics frame buffer
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 058/108] x86: fsp: Set up an MTRR for the graphics frame buffer Simon Glass
@ 2019-11-19  7:25   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  7:25 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The FSP-S may do this but at least for coral it does not. Set this up so

This is confusing. Is this bug of the FSP-S on ApolloLake, or the FSP
v2 spec does not say anything about it? Guess we need some
clarification :)

> that graphics is not deathly slow.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/lib/fsp/fsp_graphics.c | 4 ++++
>  1 file changed, 4 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 059/108] x86: fsp: Add a new arch_fsp_init_r() hook
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 059/108] x86: fsp: Add a new arch_fsp_init_r() hook Simon Glass
@ 2019-11-19  7:25   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  7:25 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> With FSP2 we need to run silicon init early after relocation. Add a new
> hook for this.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  common/board_r.c |  3 +++
>  include/init.h   | 11 +++++++++++
>  2 files changed, 14 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 060/108] x86: fsp: Allow remembering the location of FSP-S
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 060/108] x86: fsp: Allow remembering the location of FSP-S Simon Glass
@ 2019-11-19  7:25   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  7:25 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> FSP-S is used by the notify call after it has been used for silicon init.
> To avoid having to load it again, add a field to store the location.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/include/asm/global_data.h | 3 +++
>  1 file changed, 3 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 061/108] x86: fsp: Make the notify API call common
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 061/108] x86: fsp: Make the notify API call common Simon Glass
@ 2019-11-19  8:02   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:02 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The fsp_notify() API is the same for FSP1 and FSP2. Move it into a new
> common API file.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/include/asm/fsp/fsp_api.h  | 27 +++++++++++++++++++++++++++
>  arch/x86/include/asm/fsp1/fsp_api.h | 21 +++------------------
>  2 files changed, 30 insertions(+), 18 deletions(-)
>  create mode 100644 arch/x86/include/asm/fsp/fsp_api.h
>
> diff --git a/arch/x86/include/asm/fsp/fsp_api.h b/arch/x86/include/asm/fsp/fsp_api.h
> new file mode 100644
> index 00000000000..541f86ff0e8
> --- /dev/null
> +++ b/arch/x86/include/asm/fsp/fsp_api.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: Intel */
> +/*
> + * Copyright (C) 2015-2016 Intel Corp.
> + * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
> + * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
> + * Mostly taken from coreboot fsp2_0/memory_init.c

nits: is this really from coreboot fsp2_0/memory_init.c?

> + */
> +
> +#ifndef __ASM_FSP_API_H
> +#define __ASM_FSP_API_H
> +
> +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
> +};
> +
> +struct fsp_notify_params {
> +       /* Notification phase used for NotifyPhase API */
> +       enum fsp_phase  phase;
> +};
> +
> +/* FspNotify API function prototype */
> +typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
> +
> +#endif

[snip]

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 063/108] x86: Add an option to include a FIT
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 063/108] x86: Add an option to include a FIT Simon Glass
@ 2019-11-19  8:02   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:02 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Many Intel SoCs require a FIT in order to boot properly. Add an option to
> include this and enable it by default.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add help to CONFIG_FIT and don't make it 'default y'

The changelog says "dont make it default y", but the commit message
and the codes are still "default y".

>
> Changes in v2: None
>
>  arch/x86/Kconfig         | 9 +++++++++
>  arch/x86/dts/u-boot.dtsi | 6 ++++++
>  2 files changed, 15 insertions(+)
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index cbd3fc4f581..54f51e002b8 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -217,6 +217,15 @@ config SYS_X86_START16
>         depends on X86_RESET_VECTOR
>         default 0xfffff800
>
> +config X86_HAS_FIT

Can we rename this to HAVE_FIT? to be in consistent with other options
like HAVE_INTEL_ME, HAVE_FSP?

> +       bool
> +       default y
> +       help
> +         Enable inclusion of an Intel Firmware Interface Table (FIT) into the
> +         image. This table is supposed to point to microcode and the like. So
> +         far it is just a fixed table with the minimum set of headers, so that
> +         it is actually present.
> +
>  config X86_LOAD_FROM_32_BIT
>         bool "Boot from a 32-bit program"
>         help
> diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
> index 0e87b88e105..049f47c9ffd 100644
> --- a/arch/x86/dts/u-boot.dtsi
> +++ b/arch/x86/dts/u-boot.dtsi
> @@ -82,6 +82,12 @@
>         u-boot-ucode {
>                 align = <16>;
>         };
> +#ifdef CONFIG_X86_HAS_FIT
> +       intel-fit {
> +       };
> +       intel-fit-ptr {
> +       };
> +#endif
>  #ifdef CONFIG_HAVE_MRC
>         intel-mrc {
>                 offset = <CONFIG_X86_MRC_ADDR>;
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes Simon Glass
  2019-10-21  8:11   ` Andy Shevchenko
@ 2019-11-19  8:02   ` Bin Meng
  1 sibling, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:02 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Newer Intel SoCs have different ways of setting up cache-as-ram (CAR).
> Add support for these along with suitable configuration options.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Drop unneeded Kconfig file
>
> Changes in v2: None
>
>  arch/x86/Kconfig                        |  16 +
>  arch/x86/cpu/intel_common/Makefile      |   8 +
>  arch/x86/cpu/intel_common/car2.S        | 490 ++++++++++++++++++++++++
>  arch/x86/cpu/intel_common/car2_uninit.S |  87 +++++
>  4 files changed, 601 insertions(+)
>  create mode 100644 arch/x86/cpu/intel_common/car2.S
>  create mode 100644 arch/x86/cpu/intel_common/car2_uninit.S
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 54f51e002b8..69327bd746a 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -889,4 +889,20 @@ config HIGH_TABLE_SIZE
>           Increse it if the default size does not fit the board's needs.
>           This is most likely due to a large ACPI DSDT table is used.
>
> +config INTEL_CAR_CQOS
> +       bool "Support Intel Cache Quality of Service"
> +       help
> +         Cache Quality of Service allows more fine-grained control of cache
> +         usage. As result, it is possible to set up a portion of L2 cache for
> +         CAR and use the remainder for actual caching.
> +
> +#
> +# Each bit in QOS mask controls this many bytes. This is calculated as:
> +# (CACHE_WAYS / CACHE_BITS_PER_MASK) * CACHE_LINE_SIZE * CACHE_SETS
> +#
> +config CACHE_QOS_SIZE_PER_BIT
> +       hex
> +       depends on INTEL_CAR_CQOS
> +       default 0x20000 # 128 KB
> +
>  endmenu
> diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile
> index dfbc29f0475..4c733f46067 100644
> --- a/arch/x86/cpu/intel_common/Makefile
> +++ b/arch/x86/cpu/intel_common/Makefile
> @@ -8,6 +8,14 @@ obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
>  obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
>  obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
>  endif
> +
> +ifdef CONFIG_FSP_VERSION2

The new CAR should not be dependent on FSP_VERSION2. It's OK that we
implement a native U-Boot port without FSP2. Besides, when FSP2 FSP-T
is used, the car2 is not needed too.

> +obj-$(CONFIG_TPL_BUILD) += car2.o
> +ifndef CONFIG_SPL_BUILD
> +obj-y += car2_uninit.o
> +endif
> +endif
> +
>  obj-y += cpu.o
>  obj-y += fast_spi.o
>  obj-y += lpc.o
> diff --git a/arch/x86/cpu/intel_common/car2.S b/arch/x86/cpu/intel_common/car2.S
> new file mode 100644
> index 00000000000..bf01b0da849
> --- /dev/null
> +++ b/arch/x86/cpu/intel_common/car2.S
> @@ -0,0 +1,490 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2015-2016 Intel Corp.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.

The above license text is not needed, given SPDX format is already used.

> + *
> + */
> +
> +#include <config.h>
> +#include <asm/msr-index.h>
> +#include <asm/mtrr.h>
> +#include <asm/post.h>
> +#include <asm/processor-flags.h>
> +
> +#define KiB 1024
> +
> +.global car_init
> +car_init:
> +       post_code(0x20)

Looks 0x20 is occupied by POST_CAR_SIPI. Can we use a macro, and a
different value?

Please fix this globally in this file.

> +
> +       /*
> +        * Use the MTRR default type MSR as a proxy for detecting INIT#.
> +        * Reset the system if any known bits are set in that MSR. That is
> +        * an indication of the CPU not being properly reset.
> +        */
> +check_for_clean_reset:
> +       mov     $MTRR_DEF_TYPE_MSR, %ecx
> +       rdmsr
> +       and     $(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax
> +       cmp     $0, %eax
> +       jz      no_reset
> +       /* perform warm reset */
> +       movw    $0xcf9, %dx

Use IO_PORT_RESET

> +       movb    $0x06, %al

Use (SYS_RST | RST_CPU)

> +       outb    %al, %dx
> +
> +no_reset:
> +       post_code(0x21)
> +
> +       /* Clear/disable fixed MTRRs */
> +       mov     $fixed_mtrr_list_size, %ebx
> +       xor     %eax, %eax
> +       xor     %edx, %edx
> +
> +clear_fixed_mtrr:
> +       add     $-2, %ebx
> +       movzwl  fixed_mtrr_list(%ebx), %ecx
> +       wrmsr
> +       jnz     clear_fixed_mtrr
> +
> +       post_code(0x22)

Ditto

> +
> +       /* Figure put how many MTRRs we have, and clear them out */
> +       mov     $MTRR_CAP_MSR, %ecx
> +       rdmsr
> +       movzb   %al, %ebx               /* Number of variable MTRRs */
> +       mov     $MTRR_PHYS_BASE_MSR(0), %ecx
> +       xor     %eax, %eax
> +       xor     %edx, %edx
> +
> +clear_var_mtrr:
> +       wrmsr
> +       inc     %ecx
> +       wrmsr
> +       inc     %ecx
> +       dec     %ebx
> +       jnz     clear_var_mtrr
> +
> +       post_code(0x23)
> +
> +       /* Configure default memory type to uncacheable (UC) */
> +       mov     $MTRR_DEF_TYPE_MSR, %ecx
> +       rdmsr
> +       /* Clear enable bits and set default type to UC */
> +       and     $~(MTRR_DEF_TYPE_MASK | MTRR_DEF_TYPE_EN | \
> +                MTRR_DEF_TYPE_FIX_EN), %eax
> +       wrmsr
> +
> +       /* Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB

nits: wrong multi-line comment format

> +        * based on the physical address size supported for this processor
> +        * This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
> +        *
> +        * Examples:
> +        *  MTRR_PHYS_MASK_HIGH = 00000000Fh  For 36 bit addressing
> +        *  MTRR_PHYS_MASK_HIGH = 0000000FFh  For 40 bit addressing
> +        */
> +
> +       movl    $0x80000008, %eax       /* Address sizes leaf */
> +       cpuid
> +       sub     $32, %al
> +       movzx   %al, %eax
> +       xorl    %esi, %esi
> +       bts     %eax, %esi
> +       dec     %esi                    /* esi <- MTRR_PHYS_MASK_HIGH */
> +
> +       post_code(0x24)
> +
> +#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)
> +       /* Configure CAR region as write-back (WB) */
> +       mov     $MTRR_PHYS_BASE_MSR(0), %ecx
> +       mov     $CONFIG_DCACHE_RAM_BASE, %eax
> +       or      $MTRR_TYPE_WRBACK, %eax
> +       xor     %edx,%edx
> +       wrmsr
> +
> +       /* Configure the MTRR mask for the size region */
> +       mov     $MTRR_PHYS_MASK(0), %ecx
> +       mov     $CONFIG_DCACHE_RAM_SIZE, %eax   /* size mask */
> +       dec     %eax
> +       not     %eax
> +       or      $MTRR_PHYS_MASK_VALID, %eax
> +       movl    %esi, %edx      /* edx <- MTRR_PHYS_MASK_HIGH */
> +       wrmsr
> +#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
> +       /* Configure CAR region as write-back (WB) */
> +       mov     $MTRR_PHYS_BASE_MSR(0), %ecx
> +       mov     $CONFIG_DCACHE_RAM_BASE, %eax
> +       or      $MTRR_TYPE_WRBACK, %eax
> +       xor     %edx,%edx
> +       wrmsr
> +
> +       mov     $MTRR_PHYS_MASK_MSR(0), %ecx
> +       mov     $(512 * KiB), %eax      /* size mask */
> +       dec     %eax
> +       not     %eax
> +       or      $MTRR_PHYS_MASK_VALID, %eax
> +       movl    %esi, %edx      /* edx <- MTRR_PHYS_MASK_HIGH */
> +       wrmsr
> +
> +       mov     $MTRR_PHYS_BASE_MSR(1), %ecx
> +       mov     $(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
> +       or      $MTRR_TYPE_WRBACK, %eax
> +       xor     %edx,%edx
> +       wrmsr
> +
> +       mov     $MTRR_PHYS_MASK_MSR(1), %ecx
> +       mov     $(256 * KiB), %eax      /* size mask */
> +       dec     %eax
> +       not     %eax
> +       or      $MTRR_PHYS_MASK_VALID, %eax
> +       movl    %esi, %edx      /* edx <- MTRR_PHYS_MASK_HIGH */
> +       wrmsr
> +#else
> +#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
> +#endif
> +       post_code(0x25)
> +
> +       /* start */
> +/*     mov     $0xffff80a8, %ebx */
> +/*     jmp     *%ebx */
> +.globl _from_bb
> +_from_bb:
> +/*     jmp     car_init_ret */
> +       /* end */
> +
> +       /* Enable variable MTRRs */
> +       mov     $MTRR_DEF_TYPE_MSR, %ecx
> +       rdmsr
> +       or      $MTRR_DEF_TYPE_EN, %eax
> +       wrmsr
> +
> +       /* Enable caching */
> +       mov     %cr0, %eax
> +       and     $~(X86_CR0_CD | X86_CR0_NW), %eax
> +       invd
> +       mov     %eax, %cr0
> +
> +#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
> +       jmp car_nem

nits: indentation of "car_nem" not correct

> +#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
> +       jmp car_cqos

ditto

> +#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
> +       jmp car_nem_enhanced

ditto

> +#else
> +#error "No CAR mechanism selected:
> +#endif
> +       jmp     car_init_ret
> +
> +#if 0

Dead codes? If yes, please remove the whole block in #if 0

> +.global car_init_done
> +car_init_done:
> +
> +       post_code(0x29)
> +
> +       /* Setup bootblock stack */
> +       mov     $_car_stack_end, %esp
> +
> +       /* Need to align stack to 16 bytes at call instruction. Account for

nits: wrong multi-line comment format

> +          the two pushes below */
> +       andl    $0xfffffff0, %esp
> +       sub     $8, %esp
> +
> +       /*push TSC value to stack*/
> +       movd    %mm2, %eax
> +       pushl   %eax    /* tsc[63:32] */
> +       movd    %mm1, %eax
> +       pushl   %eax    /* tsc[31:0] */
> +
> +before_carstage:
> +       post_code(0x2A)
> +
> +       call    bootblock_c_entry
> +       /* Never reached */
> +#endif
> +
> +fixed_mtrr_list:
> +       .word   MTRR_FIX_64K_00000_MSR
> +       .word   MTRR_FIX_16K_80000_MSR
> +       .word   MTRR_FIX_16K_A0000_MSR
> +       .word   MTRR_FIX_4K_C0000_MSR
> +       .word   MTRR_FIX_4K_C8000_MSR
> +       .word   MTRR_FIX_4K_D0000_MSR
> +       .word   MTRR_FIX_4K_D8000_MSR
> +       .word   MTRR_FIX_4K_E0000_MSR
> +       .word   MTRR_FIX_4K_E8000_MSR
> +       .word   MTRR_FIX_4K_F0000_MSR
> +       .word   MTRR_FIX_4K_F8000_MSR
> +fixed_mtrr_list_size = . - fixed_mtrr_list
> +
> +#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
> +.global car_nem
> +car_nem:
> +       /* Disable cache eviction (setup stage) */
> +       mov     $MSR_EVICT_CTL, %ecx
> +       rdmsr
> +       or      $0x1, %eax
> +       wrmsr
> +
> +       post_code(0x26)
> +
> +       /* Clear the cache memory region. This will also fill up the cache */
> +       movl    $CONFIG_DCACHE_RAM_BASE, %edi
> +       movl    $CONFIG_DCACHE_RAM_SIZE, %ecx
> +       shr     $0x02, %ecx
> +       xor     %eax, %eax
> +       cld
> +       rep     stosl
> +
> +       post_code(0x27)
> +
> +       /* Disable cache eviction (run stage) */
> +       mov     $MSR_EVICT_CTL, %ecx
> +       rdmsr
> +       or      $0x2, %eax
> +       wrmsr
> +
> +       post_code(0x28)
> +
> +       jmp car_init_done
> +
> +#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
> +.global car_cqos
> +car_cqos:
> +       /*
> +        * Create CBM_LEN_MASK based on CBM_LEN
> +        * Get CPUID.(EAX=10H, ECX=2H):EAX.CBM_LEN[bits 4:0]
> +        */
> +       mov $0x10, %eax
> +       mov $0x2,  %ecx
> +       cpuid
> +       and $0x1F, %eax
> +       add $1, %al
> +
> +       mov $1, %ebx
> +       mov %al, %cl
> +       shl %cl, %ebx
> +       sub $1, %ebx
> +
> +       /* Store the CBM_LEN_MASK in mm3 for later use */
> +       movd %ebx, %mm3

The indentation style inside above block is not consistent with others

> +
> +       /*
> +        * Disable both L1 and L2 prefetcher. For yet-to-understood reason,
> +        * prefetchers slow down filling cache with rep stos in CQOS mode.
> +        */
> +       mov     $MSR_PREFETCH_CTL, %ecx
> +       rdmsr
> +       or      $(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
> +       wrmsr
> +
> +#if (CONFIG_DCACHE_RAM_SIZE == CONFIG_L2_CACHE_SIZE)
> +/*
> + * If CAR size is set to full L2 size, mask is calculated as all-zeros.
> + * This is not supported by the CPU/uCode.
> + */
> +#error "CQOS CAR may not use whole L2 cache area"
> +#endif
> +
> +       /* Calculate how many bits to be used for CAR */
> +       xor     %edx, %edx
> +       mov     $CONFIG_DCACHE_RAM_SIZE, %eax   /* dividend */
> +       mov     $CONFIG_CACHE_QOS_SIZE_PER_BIT, %ecx    /* divisor */
> +       div     %ecx            /* result is in eax */
> +       mov     %eax, %ecx      /* save to ecx */
> +       mov     $1, %ebx
> +       shl     %cl, %ebx
> +       sub     $1, %ebx        /* resulting mask is is in ebx */
> +
> +       /* Set this mask for initial cache fill */
> +       mov     $MSR_L2_QOS_MASK(0), %ecx
> +       rdmsr
> +       mov     %ebx, %eax
> +       wrmsr
> +
> +       /* Set CLOS selector to 0 */
> +       mov     $MSR_IA32_PQR_ASSOC, %ecx
> +       rdmsr
> +       and     $~MSR_IA32_PQR_ASSOC_MASK, %edx /* select mask 0 */
> +       wrmsr
> +
> +       /* We will need to block CAR region from evicts */
> +       mov     $MSR_L2_QOS_MASK(1), %ecx
> +       rdmsr
> +       /* Invert bits that are to be used for cache */
> +       mov     %ebx, %eax
> +       xor     $~0, %eax                       /* invert 32 bits */
> +
> +       /*
> +        * Use CBM_LEN_MASK stored in mm3 to set bits based on Capacity Bit
> +        * Mask Length.
> +        */
> +       movd    %mm3, %ebx
> +       and     %ebx, %eax
> +       wrmsr
> +
> +       post_code(0x26)
> +
> +       /* Clear the cache memory region. This will also fill up the cache */
> +       movl    $CONFIG_DCACHE_RAM_BASE, %edi
> +       movl    $CONFIG_DCACHE_RAM_SIZE, %ecx
> +       shr     $0x02, %ecx
> +       xor     %eax, %eax
> +       cld
> +       rep     stosl
> +
> +       post_code(0x27)
> +
> +       /* Cache is populated. Use mask 1 that will block evicts */
> +       mov     $MSR_IA32_PQR_ASSOC, %ecx
> +       rdmsr
> +       and     $~MSR_IA32_PQR_ASSOC_MASK, %edx /* clear index bits first */
> +       or      $1, %edx                        /* select mask 1 */
> +       wrmsr
> +
> +       /* Enable prefetchers */
> +       mov     $MSR_PREFETCH_CTL, %ecx
> +       rdmsr
> +       and     $~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
> +       wrmsr
> +
> +       post_code(0x28)
> +
> +/*     jmp car_init_done */

Is this really not used and commented out?

> +       jmp     car_init_ret
> +
> +#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
> +.global car_nem_enhanced
> +car_nem_enhanced:
> +       /* Disable cache eviction (setup stage) */
> +       mov     $MSR_EVICT_CTL, %ecx
> +       rdmsr
> +       or      $0x1, %eax
> +       wrmsr
> +       post_code(0x26)
> +
> +       /* Create n-way set associativity of cache */
> +       xorl    %edi, %edi
> +find_llc_subleaf:
> +       movl    %edi, %ecx
> +       movl    $0x04, %eax
> +       cpuid
> +       inc     %edi
> +       and     $0xe0, %al      /* EAX[7:5] = Cache Level */
> +       cmp     $0x60, %al      /* Check to see if it is LLC */
> +       jnz     find_llc_subleaf
> +
> +       /*
> +        * Set MSR 0xC91 IA32_L3_MASK_! = 0xE/0xFE/0xFFE/0xFFFE
> +        * for 4/8/16 way of LLC
> +       */
> +       shr     $22, %ebx
> +       inc     %ebx
> +       /* Calculate n-way associativity of LLC */
> +       mov     %bl, %cl
> +
> +       /*
> +        * Maximizing RO cacheability while locking in the CAR to a
> +        * single way since that particular way won't be victim candidate
> +        * for evictions.
> +        * This has been done after programing LLC_WAY_MASK_1 MSR
> +        * with desired LLC way as mentioned below.
> +        *
> +        * Hence create Code and Data Size as per request
> +        * Code Size (RO) : Up to 16M
> +        * Data Size (RW) : Up to 256K
> +        */
> +       movl    $0x01, %eax
> +       /*
> +        * LLC Ways -> LLC_WAY_MASK_1:
> +        *  4: 0x000E
> +        *  8: 0x00FE
> +        * 12: 0x0FFE
> +        * 16: 0xFFFE
> +        *
> +        * These MSRs contain one bit per each way of LLC
> +        * - If this bit is '0' - the way is protected from eviction
> +        * - If this bit is '1' - the way is not protected from eviction
> +        */
> +       shl     %cl, %eax
> +       subl    $0x02, %eax
> +       movl    $MSR_IA32_L3_MASK_1, %ecx
> +       xorl    %edx, %edx
> +       wrmsr
> +       /*
> +        * Set MSR 0xC92 IA32_L3_MASK_2 = 0x1
> +        *
> +        * For SKL SOC, data size remains 256K consistently.
> +        * Hence, creating 1-way associative cache for Data
> +       */
> +       mov     $MSR_IA32_L3_MASK_2, %ecx
> +       mov     $0x01, %eax
> +       xorl    %edx, %edx
> +       wrmsr
> +       /*
> +        * Set MSR_IA32_PQR_ASSOC = 0x02
> +        *
> +        * Possible values:
> +        * 0: Default value, no way mask should be applied
> +        * 1: Apply way mask 1 to LLC
> +        * 2: Apply way mask 2 to LLC
> +        * 3: Shouldn't be use in NEM Mode
> +        */
> +       movl    $MSR_IA32_PQR_ASSOC, %ecx
> +       movl    $0x02, %eax
> +       xorl    %edx, %edx
> +       wrmsr
> +
> +       movl    $CONFIG_DCACHE_RAM_BASE, %edi
> +       movl    $CONFIG_DCACHE_RAM_SIZE, %ecx
> +       shr     $0x02, %ecx
> +       xor     %eax, %eax
> +       cld
> +       rep     stosl
> +       /*
> +        * Set MSR_IA32_PQR_ASSOC = 0x01
> +        * At this stage we apply LLC_WAY_MASK_1 to the cache.
> +        * i.e. way 0 is protected from eviction.
> +       */
> +       movl    $MSR_IA32_PQR_ASSOC, %ecx
> +       movl    $0x01, %eax
> +       xorl    %edx, %edx
> +       wrmsr
> +
> +       post_code(0x27)
> +       /*
> +        * Enable No-Eviction Mode Run State by setting
> +        * NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
> +        */
> +
> +       movl    $MSR_EVICT_CTL, %ecx
> +       rdmsr
> +       orl     $0x02, %eax
> +       wrmsr
> +
> +       post_code(0x28)
> +
> +       jmp car_init_done

nits: incorrect indentation of car_init_done

> +#endif
> +
> +#if CONFIG_IS_ENABLED(X86_16BIT_INIT)
> +_dt_ucode_base_size:
> +       /* These next two fields are filled in by binman */
> +.globl ucode_base
> +ucode_base:    /* Declared in microcode.h */
> +       .long   0                       /* microcode base */
> +.globl ucode_size
> +ucode_size:    /* Declared in microcode.h */
> +       .long   0                       /* microcode size */
> +       .long   CONFIG_SYS_MONITOR_BASE /* code region base */
> +       .long   CONFIG_SYS_MONITOR_LEN  /* code region size */
> +#endif
> diff --git a/arch/x86/cpu/intel_common/car2_uninit.S b/arch/x86/cpu/intel_common/car2_uninit.S
> new file mode 100644
> index 00000000000..aba3a5381e5
> --- /dev/null
> +++ b/arch/x86/cpu/intel_common/car2_uninit.S
> @@ -0,0 +1,87 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2017 Intel Corp.
> + * Copyright 2019 Google LLC
> + * Taken from coreboot file exit_car.S
> + */
> +
> +#include <config.h>
> +#include <asm/msr-index.h>
> +#include <asm/mtrr.h>
> +
> +.text
> +.global car_uninit
> +car_uninit:
> +
> +       /*
> +        * Retrieve return address from stack as it will get trashed below if
> +        * execution is utilizing the cache-as-ram stack.
> +        */
> +       pop     %ebx
> +
> +       /* Disable MTRRs */
> +       mov     $(MTRR_DEF_TYPE_MSR), %ecx
> +       rdmsr
> +       and     $(~(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN)), %eax
> +       wrmsr
> +
> +#ifdef CONFIG_INTEL_CAR_NEM
> +.global car_nem_teardown
> +car_nem_teardown:
> +
> +       /* invalidate cache contents */
> +       invd
> +
> +       /* Knock down bit 1 then bit 0 of NEM control not combining steps */
> +       mov     $(MSR_EVICT_CTL), %ecx
> +       rdmsr
> +       and     $(~(1 << 1)), %eax
> +       wrmsr
> +       and     $(~(1 << 0)), %eax
> +       wrmsr
> +
> +#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
> +.global car_cqos_teardown
> +car_cqos_teardown:
> +
> +       /* Go back to all-evicting mode, set both masks to all-1s */
> +       mov     $MSR_L2_QOS_MASK(0), %ecx
> +       rdmsr
> +       mov     $~0, %al
> +       wrmsr
> +
> +       mov     $MSR_L2_QOS_MASK(1), %ecx
> +       rdmsr
> +       mov     $~0, %al
> +       wrmsr
> +
> +       /* Reset CLOS selector to 0 */
> +       mov     $MSR_IA32_PQR_ASSOC, %ecx
> +       rdmsr
> +       and     $~MSR_IA32_PQR_ASSOC_MASK, %edx
> +       wrmsr
> +
> +#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
> +.global car_nem_enhanced_teardown
> +car_nem_enhanced_teardown:
> +
> +       /* invalidate cache contents */
> +       invd
> +
> +       /* Knock down bit 1 then bit 0 of NEM control not combining steps */
> +       mov     $(MSR_EVICT_CTL), %ecx
> +       rdmsr
> +       and     $(~(1 << 1)), %eax
> +       wrmsr
> +       and     $(~(1 << 0)), %eax
> +       wrmsr
> +
> +       /* Reset CLOS selector to 0 */
> +       mov     $IA32_PQR_ASSOC, %ecx
> +       rdmsr
> +       and     $~IA32_PQR_ASSOC_MASK, %edx
> +       wrmsr
> +#endif
> +
> +       /* Return to caller */
> +       jmp     *%ebx
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 065/108] x86: Disable microcode section for FSP2
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 065/108] x86: Disable microcode section for FSP2 Simon Glass
@ 2019-11-19  8:02   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:02 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present we don't support loading microcode with FSP2. The correct way
> to do this is by adding it to the FIT. For now, disable including
> microcode in the image.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Drop unnecessary #else part of CONFIG_HAVE_MICROCODE
>
> Changes in v2: None
>
>  arch/x86/Kconfig         | 4 ++++
>  arch/x86/dts/u-boot.dtsi | 7 +++++++
>  2 files changed, 11 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 066/108] x86: Update the fsp command for FSP2
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 066/108] x86: Update the fsp command " Simon Glass
@ 2019-11-19  8:34   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:34 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The current 'fsp' command only works with FSP1. Update it to handle FSP2
> as well. Convert everything to hex which is what U-Boot uses.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Convert code to use hex increased of decimal
> - Update the 'fsp' command for FSP2, instead of disabling it
>
> Changes in v2: None
>
>  cmd/x86/fsp.c | 59 ++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 39 insertions(+), 20 deletions(-)
>
> diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c
> index b3b663021bc..fd5328db181 100644
> --- a/cmd/x86/fsp.c
> +++ b/cmd/x86/fsp.c
> @@ -5,19 +5,30 @@
>
>  #include <common.h>
>  #include <command.h>
> -#include <asm/fsp1/fsp_support.h>
> +#include <asm/fsp/fsp_support.h>
>
>  DECLARE_GLOBAL_DATA_PTR;
>
>  static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  {
> -       struct fsp_header *hdr = fsp_find_header();
> -       u32 img_addr = hdr->img_base;
> -       char *sign = (char *)&hdr->sign;
> +       struct fsp_header *hdr;
> +       u32 img_addr;
> +       char *sign;
> +       uint addr;
>         int i;
>
> -       printf("FSP    : binary 0x%08x, header 0x%08x\n",
> -              CONFIG_FSP_ADDR, (int)hdr);
> +#ifdef CONFIG_FSP_VERSION2
> +       hdr = gd->arch.fsp_s_hdr;

Only FSP-S is displayed?

> +       img_addr = hdr->img_base;
> +       addr = img_addr;
> +#else
> +       addr = CONFIG_FSP_ADDR;
> +       hdr = fsp_find_header();
> +       img_addr = hdr->img_base;
> +#endif
> +       sign = (char *)&hdr->sign;
> +
> +       printf("FSP    : binary %08x, header %08x\n", addr, (int)hdr);
>         printf("Header : sign ");
>         for (i = 0; i < sizeof(hdr->sign); i++)
>                 printf("%c", *sign++);
> @@ -34,24 +45,32 @@ static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>         printf(", id ");
>         for (i = 0; i < ARRAY_SIZE(hdr->img_id); i++)
>                 printf("%c", hdr->img_id[i]);
> -       printf(", addr 0x%08x, size %d\n", img_addr, hdr->img_size);
> -       if (hdr->hdr_rev == FSP_HEADER_REVISION_2) {
> +       printf(", addr %08x, size %d\n", img_addr, hdr->img_size);

size %x? since commit message says: "Convert everything to hex"

> +       if (hdr->hdr_rev >= FSP_HEADER_REVISION_1) {
>                 printf("GFX    :%ssupported\n",
>                        hdr->img_attr & FSP_ATTR_GRAPHICS_SUPPORT ? " " : " un");
>         }
> -       printf("VPD    : addr 0x%08x, size %d\n",
> +       printf("VPD    : addr %08x, size %x\n",
>                hdr->cfg_region_off + img_addr, hdr->cfg_region_size);
> -       printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
> -       printf("\tTempRamInit : 0x%08x\n", hdr->fsp_tempram_init + img_addr);
> -       printf("\tFspInit     : 0x%08x\n", hdr->fsp_init + img_addr);
> -       printf("\tFspNotify   : 0x%08x\n", hdr->fsp_notify + img_addr);
> -       if (hdr->hdr_rev == FSP_HEADER_REVISION_2) {
> -               printf("\tMemoryInit  : 0x%08x\n",
> -                      hdr->fsp_mem_init + img_addr);
> -               printf("\tTempRamExit : 0x%08x\n",
> -                      hdr->fsp_tempram_exit + img_addr);
> -               printf("\tSiliconInit : 0x%08x\n",
> -                      hdr->fsp_silicon_init + img_addr);
> +       if (hdr->hdr_rev <= FSP_HEADER_REVISION_2)
> +               printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
> +       if (hdr->fsp_tempram_init)
> +               printf("\tTempRamInit : %08x\n",
> +                      hdr->fsp_tempram_init + img_addr);
> +       if (hdr->fsp_init)
> +               printf("\tFspInit     : %08x\n", hdr->fsp_init + img_addr);
> +       if (hdr->fsp_notify)
> +               printf("\tFspNotify   : %08x\n", hdr->fsp_notify + img_addr);
> +       if (hdr->hdr_rev >= FSP_HEADER_REVISION_1) {
> +               if (hdr->fsp_mem_init)
> +                       printf("\tMemoryInit  : %08x\n",
> +                              hdr->fsp_mem_init + img_addr);
> +               if (hdr->fsp_tempram_exit)
> +                       printf("\tTempRamExit : %08x\n",
> +                              hdr->fsp_tempram_exit + img_addr);
> +               if (hdr->fsp_silicon_init)
> +                       printf("\tSiliconInit : %08x\n",
> +                              hdr->fsp_silicon_init + img_addr);
>         }
>
>         return 0;
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 067/108] x86: Update .dtsi file for FSP2
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 067/108] x86: Update .dtsi file " Simon Glass
@ 2019-11-19  8:34   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:34 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Include the IFWI section and the FSP-M binary. The FSP-T binary is not
> currently used, as CAR is set up manually.
>
> Also drop the FSP binary as this relates only to FSP1.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add FSP-S and VBT also
>
> Changes in v2: None
>
>  arch/x86/dts/u-boot.dtsi | 35 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 34 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot Simon Glass
@ 2019-11-19  8:34   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:34 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The existing work-around for positioning U-Boot in the ROM when it
> actually runs from RAM still exists and there is not obvious way to change
> this.
>
> Add a proper Kconfig option to handle this case. This also adds a new bool
> property to indicate whether CONFIG_SYS_TEXT_BASE exists.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  Kconfig                                |  9 ++++++---
>  arch/x86/Kconfig                       |  5 +++++
>  arch/x86/dts/u-boot.dtsi               | 18 +++---------------
>  configs/chromebook_samus_tpl_defconfig |  1 +
>  4 files changed, 15 insertions(+), 18 deletions(-)
>
> diff --git a/Kconfig b/Kconfig
> index 66b059f749a..86161b662de 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -530,9 +530,14 @@ config SYS_EXTRA_OPTIONS
>           configuration to Kconfig. Since this option will be removed sometime,
>           new boards should not use this option.
>
> -config SYS_TEXT_BASE
> +config HAS_SYS_TEXT_BASE

nits: HAVE_SYS_TEXT_BASE for consistent names

> +       bool
>         depends on !NIOS2 && !XTENSA
>         depends on !EFI_APP
> +       default y
> +
> +config SYS_TEXT_BASE
> +       depends on HAS_SYS_TEXT_BASE
>         default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3
>         default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S
>         default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I
> @@ -541,8 +546,6 @@ config SYS_TEXT_BASE
>         help
>           The address in memory that U-Boot will be running from, initially.
>
> -
> -
>  config SYS_CLK_FREQ
>         depends on ARC || ARCH_SUNXI || MPC83xx
>         int "CPU clock frequency"
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 37e94d8913a..f015e380f90 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -909,4 +909,9 @@ config CACHE_QOS_SIZE_PER_BIT
>         depends on INTEL_CAR_CQOS
>         default 0x20000 # 128 KB
>
> +config X86_OFFSET_U_BOOT
> +       hex "Offset of U-Boot in ROM image"
> +       depends on HAS_SYS_TEXT_BASE
> +       default SYS_TEXT_BASE
> +
>  endmenu
> diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
> index 51d003dcfe1..66c4fdc8f8a 100644
> --- a/arch/x86/dts/u-boot.dtsi
> +++ b/arch/x86/dts/u-boot.dtsi
> @@ -50,7 +50,7 @@
>         u-boot-spl-dtb {
>         };
>         u-boot {
> -               offset = <CONFIG_SYS_TEXT_BASE>;
> +               offset = <CONFIG_X86_OFFSET_U_BOOT>;
>         };
>  #elif defined(CONFIG_SPL)
>         u-boot-spl-with-ucode-ptr {
> @@ -60,23 +60,11 @@
>                 type = "u-boot-dtb-with-ucode";
>         };
>         u-boot {
> -               /*
> -                * TODO(sjg at chromium.org):
> -                * Normally we use CONFIG_SYS_TEXT_BASE as the flash offset. But
> -                * for boards with textbase in SDRAM we cannot do this. Just use
> -                * an assumed-valid value (1MB before the end of flash) here so
> -                * that we can actually build an image for coreboot, etc.
> -                * We need a better solution, perhaps a separate Kconfig.
> -                */
> -#if CONFIG_SYS_TEXT_BASE == 0x1110000
> -               offset = <0xfff00000>;
> -#else
> -               offset = <CONFIG_SYS_TEXT_BASE>;
> -#endif
> +               offset = <CONFIG_X86_OFFSET_U_BOOT>;
>         };
>  #else
>         u-boot-with-ucode-ptr {
> -               offset = <CONFIG_SYS_TEXT_BASE>;
> +               offset = <CONFIG_X86_OFFSET_U_BOOT>;
>         };
>  #endif
>  #ifdef CONFIG_HAVE_MICROCODE
> diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig
> index 28f23cfe125..c7f125eaa40 100644
> --- a/configs/chromebook_samus_tpl_defconfig
> +++ b/configs/chromebook_samus_tpl_defconfig
> @@ -13,6 +13,7 @@ CONFIG_HAVE_REFCODE=y
>  CONFIG_SMP=y
>  CONFIG_HAVE_VGA_BIOS=y
>  CONFIG_SPL_TEXT_BASE=0xffe70000
> +CONFIG_X86_OFFSET_U_BOOT=0xfff00000

Should we update other x86 board defconfig files for this option?

>  CONFIG_BOOTSTAGE=y
>  CONFIG_BOOTSTAGE_REPORT=y
>  CONFIG_SHOW_BOOT_PROGRESS=y
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 069/108] x86: Add an option to control the position of SPL
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 069/108] x86: Add an option to control the position of SPL Simon Glass
@ 2019-11-19  8:34   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:34 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> For apollolake SPL is run from CAR (cache-as-RAM) which is in a different
> location from where SPL must be placed in ROM. In other words, although
> SPL runs before SDRAM is set up, it is not execute-in-place (XIP).
>
> Add a Kconfig option for the ROM position.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add SPL condition to the option
>
> Changes in v2: None
>
>  arch/x86/Kconfig         | 5 +++++
>  arch/x86/dts/u-boot.dtsi | 4 ++--
>  2 files changed, 7 insertions(+), 2 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 070/108] x86: Add an fdtmap and image-header
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 070/108] x86: Add an fdtmap and image-header Simon Glass
@ 2019-11-19  8:34   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19  8:34 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add these entries to the ROM so that we can list the contents of an image
> with 'binman ls'. The image-header is not essential but does speed up
> access.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/dts/u-boot.dtsi | 5 +++++
>  1 file changed, 5 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 071/108] x86: Don't repeat microcode in U-Boot if not needed
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 071/108] x86: Don't repeat microcode in U-Boot if not needed Simon Glass
@ 2019-11-19 13:33   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:33 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present if SPL sets up the microcode then it is still included in
> U-Boot as well. This is wasteful as microcode is large. Adjust the logic
> in the image to prevent this.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/dts/u-boot.dtsi | 7 +++++++
>  1 file changed, 7 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 072/108] x86: Separate out U-Boot and device tree in ROM image
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 072/108] x86: Separate out U-Boot and device tree in ROM image Simon Glass
@ 2019-11-19 13:33   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:33 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present binman does not support updating a device tree that is part of
> U-Boot (i.e u-boot.bin). Separate the entries into two so that we can get
> updated entry information. This makes binman_entry_find() work correctly.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/dts/u-boot.dtsi | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 073/108] x86: Make MSR_PKG_POWER_SKU common
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 073/108] x86: Make MSR_PKG_POWER_SKU common Simon Glass
@ 2019-11-19 13:33   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:33 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> This is used on several boards so add it to the common file. Also add a
> useful power-limit value while we are here.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/include/asm/arch-broadwell/cpu.h         | 1 -
>  arch/x86/include/asm/arch-ivybridge/model_206ax.h | 1 -
>  arch/x86/include/asm/msr-index.h                  | 9 ++++++++-
>  3 files changed, 8 insertions(+), 3 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 074/108] spi: Correct operations check in dm_spi_xfer()
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 074/108] spi: Correct operations check in dm_spi_xfer() Simon Glass
@ 2019-11-19 13:33   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:33 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> At present we have to have an xfer() method even if it does nothing. This
> is not correct, so fix it.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c        | 9 +--------
>  drivers/spi/spi-uclass.c | 5 ++++-
>  include/spi.h            | 2 +-
>  3 files changed, 6 insertions(+), 10 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default Simon Glass
@ 2019-11-19 13:33   ` Bin Meng
  2019-11-20  5:22     ` Vignesh Raghavendra
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:33 UTC (permalink / raw)
  To: u-boot

+Vignesh

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> We don't normally need this on x86 unless the size of SPI flash devices is
> larger than 16MB. This can be enabled by particular SoCs as needed, since
> it adds to code size.
>
> Drop the default enabling of this option on x86.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/Kconfig | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index b8ca2bdedd5..320baeeb3eb 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -125,7 +125,6 @@ config FSL_DSPI
>
>  config ICH_SPI
>         bool "Intel ICH SPI driver"
> -       imply SPI_FLASH_BAR

This was added via:

commit 6d82517836418f984b7b4c05cf1427d7b49b1169
Author: Vignesh R <vigneshr@ti.com>
Date:   Tue Feb 5 11:29:28 2019 +0530

    configs: Don't use SPI_FLASH_BAR as default

    Now that new SPI NOR layer uses stateless 4 byte opcodes by default,
    don't enable SPI_FLASH_BAR. For SPI controllers that cannot support
    4-byte addressing, (stm32_qspi.c, fsl_qspi.c, mtk_qspi.c, ich.c,
    renesas_rpc_spi.c) add an imply clause to enable SPI_FLASH_BAR so as to
    not break functionality.

The commit message says: SPI_FLASH_BAR was added so as to not break
functionality.

I don't have board to test right now. Vignesh could you please have a
review? Thanks!

>         help
>           Enable the Intel ICH SPI driver. This driver can be used to
>           access the SPI NOR flash on platforms embedding this Intel
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 076/108] spi: ich: Move init function just above probe()
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 076/108] spi: ich: Move init function just above probe() Simon Glass
@ 2019-11-19 13:52   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> It is annoying to have some of the init code in a different part of the
> file. Move ich_init_controller() to just above probe() to keep things
> together.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 122 +++++++++++++++++++++++-----------------------
>  1 file changed, 61 insertions(+), 61 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function Simon Glass
@ 2019-11-19 13:53   ` Bin Meng
  2019-11-19 17:53     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:53 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Reduce the size of the probe function but putting this code into its own
> function.
>

It's unclear to me why this brings any benefit? The size of the probe
function indeed is reduced, but whole file size does not change, no?

> Also remove the assumption that the PCH is always a parent of the SPI
> controller, as this is not the case APL platforms. Use driver model to
> find the PCH instead.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 55 +++++++++++++++++++++++++++++++----------------
>  drivers/spi/ich.h |  1 +
>  2 files changed, 38 insertions(+), 18 deletions(-)
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 078/108] spi: ich: Convert to livetree
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 078/108] spi: ich: Convert to livetree Simon Glass
@ 2019-11-19 13:53   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:53 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Use dev_get_driver_data() to obtain the device type. It has the same
> effect and is shorter.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 22 +++++-----------------
>  1 file changed, 5 insertions(+), 17 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 079/108] spi: ich: Fix header order
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 079/108] spi: ich: Fix header order Simon Glass
@ 2019-11-19 13:53   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:53 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Move the header files into the right order.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 080/108] spi: ich: Various small tidy-ups
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 080/108] spi: ich: Various small tidy-ups Simon Glass
@ 2019-11-19 13:53   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 13:53 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Use debug() instead of printf() to reduce code size and change a bool
> return value to the use the 'bool' type. Also drop the global data
> declaration since it not actually used. Finally, set the log category.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 17 ++++++++---------
>  1 file changed, 8 insertions(+), 9 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata Simon Glass
@ 2019-11-19 14:36   ` Bin Meng
  2019-11-19 17:53     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> It is useful to store the mmio base in platdata. It reduces the amount of
> casting needed. Update the code and move the struct to the C file at the
> same time, as we will need to use with of-platdata.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 27 +++++++++++++--------------
>  drivers/spi/ich.h |  5 -----
>  2 files changed, 13 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index e2bc77bbd58..7f73f096ecb 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -27,6 +27,12 @@
>  #define debug_trace(x, args...)
>  #endif
>
> +struct ich_spi_platdata {
> +       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> +       bool lockdown;                  /* lock down controller settings? */
> +       ulong mmio_base;                /* Base of MMIO registers */
> +};
> +
>  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
>  {
>         u8 value = readb(priv->base + reg);
> @@ -466,16 +472,9 @@ static int ich_init_controller(struct udevice *dev,
>                                struct ich_spi_platdata *plat,
>                                struct ich_spi_priv *ctlr)
>  {
> -       ulong sbase_addr;
> -       void *sbase;
> -
> -       /* SBASE is similar */
> -       pch_get_spi_base(dev->parent, &sbase_addr);
> -       sbase = (void *)sbase_addr;
> -       debug("%s: sbase=%p\n", __func__, sbase);
> -
> +       ctlr->base = (void *)plat->mmio_base;
>         if (plat->ich_version == ICHV_7) {
> -               struct ich7_spi_regs *ich7_spi = sbase;
> +               struct ich7_spi_regs *ich7_spi = ctlr->base;
>
>                 ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
>                 ctlr->menubytes = sizeof(ich7_spi->opmenu);
> @@ -487,9 +486,8 @@ static int ich_init_controller(struct udevice *dev,
>                 ctlr->control = offsetof(struct ich7_spi_regs, spic);
>                 ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
>                 ctlr->preop = offsetof(struct ich7_spi_regs, preop);
> -               ctlr->base = ich7_spi;
>         } else if (plat->ich_version == ICHV_9) {
> -               struct ich9_spi_regs *ich9_spi = sbase;
> +               struct ich9_spi_regs *ich9_spi = ctlr->base;
>
>                 ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
>                 ctlr->menubytes = sizeof(ich9_spi->opmenu);
> @@ -504,7 +502,6 @@ static int ich_init_controller(struct udevice *dev,
>                 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
>                 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
>                 ctlr->pr = &ich9_spi->pr[0];
> -               ctlr->base = ich9_spi;
>         } else {
>                 debug("ICH SPI: Unrecognised ICH version %d\n",
>                       plat->ich_version);
> @@ -515,8 +512,8 @@ static int ich_init_controller(struct udevice *dev,
>         ctlr->max_speed = 20000000;
>         if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
>                 ctlr->max_speed = 33000000;
> -       debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
> -             plat->ich_version, ctlr->base, ctlr->max_speed);
> +       debug("ICH SPI: Version ID %d detected at %lx, speed %ld\n",
> +             plat->ich_version, plat->mmio_base, ctlr->max_speed);
>
>         ich_set_bbar(ctlr, 0);
>
> @@ -601,6 +598,8 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
>         plat->ich_version = dev_get_driver_data(dev);
>         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
>
> +       pch_get_spi_base(dev->parent, &plat->mmio_base);

In patch [77], spi: ich: Move the protection/lockdown code into a
function, we already removed the assumption of dev->parent, but used
priv->pch for the PCH device.

> +
>         return 0;
>  }
>
> diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
> index 77057878a5d..623b2c547a6 100644
> --- a/drivers/spi/ich.h
> +++ b/drivers/spi/ich.h
> @@ -168,11 +168,6 @@ enum ich_version {
>         ICHV_9,
>  };
>
> -struct ich_spi_platdata {
> -       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> -       bool lockdown;                  /* lock down controller settings? */
> -};

I don't understand why moving this struct to C file?

> -
>  struct ich_spi_priv {
>         int opmenu;
>         int menubytes;
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size()
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size() Simon Glass
@ 2019-11-19 14:36   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> This incorrectly shortens read operations if there is a maximum write size
> but no maximum read size. Fix it.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index 7f73f096ecb..b28f3423584 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -424,9 +424,11 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
>                 page_offset = do_div(aux, ICH_BOUNDARY);
>         }
>
> -       if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
> -               op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> -                                     slave->max_read_size);
> +       if (op->data.dir == SPI_MEM_DATA_IN) {
> +               if (slave->max_read_size) {
> +                       op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> +                                             slave->max_read_size);
> +               }

Isn't the changed one the same as the old codes?

>         } else if (slave->max_write_size) {
>                 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
>                                       slave->max_write_size);
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi Simon Glass
@ 2019-11-19 14:36   ` Bin Meng
  2019-11-19 17:53     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> The Intel Fast SPI interface is similar to ICH. Add of-platdata support
> for this using the "intel,fast-spi" compatible string.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 17 ++++++++++++++---
>  1 file changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index b28f3423584..ae3bff36bba 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -10,6 +10,7 @@
>  #include <common.h>
>  #include <div64.h>
>  #include <dm.h>
> +#include <dt-structs.h>
>  #include <errno.h>
>  #include <malloc.h>
>  #include <pch.h>
> @@ -28,9 +29,13 @@
>  #endif
>
>  struct ich_spi_platdata {
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +       struct dtd_intel_fast_spi dtplat;
> +#endif
>         enum ich_version ich_version;   /* Controller version, 7 or 9 */
>         bool lockdown;                  /* lock down controller settings? */
>         ulong mmio_base;                /* Base of MMIO registers */
> +       pci_dev_t bdf;                  /* PCI address used by of-platdata */
>  };
>
>  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> @@ -597,10 +602,16 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
>  {
>         struct ich_spi_platdata *plat = dev_get_platdata(dev);
>
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
>         plat->ich_version = dev_get_driver_data(dev);
>         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> -
>         pch_get_spi_base(dev->parent, &plat->mmio_base);
> +#else
> +       plat->ich_version = ICHV_APL;

I don't think the ICH_VERSION is something that is controlled via OF_PLATDATA.

> +       plat->mmio_base = plat->dtplat.early_regs[0];
> +       plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> +#endif
> +       debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
>
>         return 0;
>  }
> @@ -628,8 +639,8 @@ static const struct udevice_id ich_spi_ids[] = {
>         { }
>  };
>
> -U_BOOT_DRIVER(ich_spi) = {
> -       .name   = "ich_spi",
> +U_BOOT_DRIVER(intel_fast_spi) = {

Why changing the driver name?

> +       .name   = "intel_fast_spi",
>         .id     = UCLASS_SPI,
>         .of_match = ich_spi_ids,
>         .ops    = &ich_spi_ops,
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method Simon Glass
@ 2019-11-19 14:36   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add this method so that the memory-mapped location of the SPI flash can
> be queried.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index ae1dc64bde8..ec0f77f6e40 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -610,6 +610,37 @@ static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
>         return ret;
>  }
>
> +static int ich_get_mmap_bus(struct udevice *bus, ulong *map_basep,
> +                           uint *map_sizep, uint *offsetp)
> +{
> +       pci_dev_t spi_bdf;
> +
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> +       struct pci_child_platdata *pplat = dev_get_parent_platdata(bus);
> +
> +       spi_bdf = pplat->devfn;
> +#else
> +       struct ich_spi_platdata *plat = dev_get_platdata(bus);
> +
> +       /*
> +        * We cannot rely on plat->bdf being set up yet since this method can
> +        * be called before the device is probed. Use the of-platdata directly
> +        * instead.
> +        */
> +       spi_bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> +#endif
> +
> +       return fast_spi_get_bios_mmap(spi_bdf, map_basep, map_sizep, offsetp);

I think we should move fast_spi_get_bios_mmap() to this driver,
instead of having the ICH driver depend on something external.

> +}
> +
> +static int ich_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
> +                       uint *offsetp)
> +{
> +       struct udevice *bus = dev_get_parent(dev);
> +
> +       return ich_get_mmap_bus(bus, map_basep, map_sizep, offsetp);
> +}
> +
>  static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
>  {
>         unsigned int page_offset;
> @@ -826,6 +857,7 @@ static const struct dm_spi_ops ich_spi_ops = {
>         .set_speed      = ich_spi_set_speed,
>         .set_mode       = ich_spi_set_mode,
>         .mem_ops        = &ich_controller_mem_ops,
> +       .get_mmap       = ich_get_mmap,
>         /*
>          * cs_info is not needed, since we require all chip selects to be
>          * in the device tree explicitly
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 084/108] spi: ich: Support hardware sequencing
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 084/108] spi: ich: Support hardware sequencing Simon Glass
@ 2019-11-19 14:36   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Apollolake (APL) only supports hardware sequencing. Add support for this
> into the SPI driver, as an option.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 205 +++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/spi/ich.h |  39 +++++++++
>  2 files changed, 241 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index ae3bff36bba..ae1dc64bde8 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -17,7 +17,9 @@
>  #include <pci.h>
>  #include <pci_ids.h>
>  #include <spi.h>
> +#include <spi_flash.h>
>  #include <spi-mem.h>
> +#include <asm/fast_spi.h>
>  #include <asm/io.h>
>
>  #include "ich.h"
> @@ -36,6 +38,7 @@ struct ich_spi_platdata {
>         bool lockdown;                  /* lock down controller settings? */
>         ulong mmio_base;                /* Base of MMIO registers */
>         pci_dev_t bdf;                  /* PCI address used by of-platdata */
> +       bool hwseq;                     /* Use hardware sequencing (not s/w) */
>  };
>
>  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> @@ -244,7 +247,8 @@ static void ich_spi_config_opcode(struct udevice *dev)
>         ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
>  }
>
> -static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
> +static int ich_spi_exec_op_swseq(struct spi_slave *slave,
> +                                const struct spi_mem_op *op)
>  {
>         struct udevice *bus = dev_get_parent(slave->dev);
>         struct ich_spi_platdata *plat = dev_get_platdata(bus);
> @@ -415,6 +419,197 @@ static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
>         return 0;
>  }
>
> +/*
> + * Ensure read/write xfer len is not greater than SPIBAR_FDATA_FIFO_SIZE and
> + * that the operation does not cross page boundary.
> + */
> +static uint get_xfer_len(u32 offset, int len, int page_size)
> +{
> +       uint xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE);
> +       uint bytes_left = ALIGN(offset, page_size) - offset;
> +
> +       if (bytes_left)
> +               xfer_len = min(xfer_len, bytes_left);
> +
> +       return xfer_len;
> +}
> +
> +/* Fill FDATAn FIFO in preparation for a write transaction */
> +static void fill_xfer_fifo(struct fast_spi_regs *regs, const void *data,
> +                          uint len)
> +{
> +       memcpy(regs->fdata, data, len);
> +}
> +
> +/* Drain FDATAn FIFO after a read transaction populates data */
> +static void drain_xfer_fifo(struct fast_spi_regs *regs, void *dest, uint len)
> +{
> +       memcpy(dest, regs->fdata, len);
> +}
> +
> +/* Fire up a transfer using the hardware sequencer */
> +static void start_hwseq_xfer(struct fast_spi_regs *regs, uint hsfsts_cycle,
> +                            uint offset, uint len)
> +{
> +       /* Make sure all W1C status bits get cleared */
> +       u32 hsfsts;
> +
> +       hsfsts = readl(&regs->hsfsts_ctl);
> +       hsfsts &= ~(HSFSTS_FCYCLE_MASK | HSFSTS_FDBC_MASK);
> +       hsfsts |= HSFSTS_AEL | HSFSTS_FCERR | HSFSTS_FDONE;
> +
> +       /* Set up transaction parameters */
> +       hsfsts |= hsfsts_cycle << HSFSTS_FCYCLE_SHIFT;
> +       hsfsts |= ((len - 1) << HSFSTS_FDBC_SHIFT) & HSFSTS_FDBC_MASK;
> +       hsfsts |= HSFSTS_FGO;
> +
> +       writel(offset, &regs->faddr);
> +       writel(hsfsts, &regs->hsfsts_ctl);
> +}
> +
> +static int wait_for_hwseq_xfer(struct fast_spi_regs *regs, uint offset)
> +{
> +       ulong start;
> +       u32 hsfsts;
> +
> +       start = get_timer(0);
> +       do {
> +               hsfsts = readl(&regs->hsfsts_ctl);
> +               if (hsfsts & HSFSTS_FCERR) {
> +                       debug("SPI transaction error at offset %x HSFSTS = %08x\n",
> +                             offset, hsfsts);
> +                       return -EIO;
> +               }
> +               if (hsfsts & HSFSTS_AEL)
> +                       return -EPERM;
> +
> +               if (hsfsts & HSFSTS_FDONE)
> +                       return 0;
> +       } while (get_timer(start) < SPIBAR_HWSEQ_XFER_TIMEOUT_MS);
> +
> +       debug("SPI transaction timeout at offset %x HSFSTS = %08x, timer %d\n",
> +             offset, hsfsts, (uint)get_timer(start));
> +
> +       return -ETIMEDOUT;
> +}
> +
> +/**
> + * exec_sync_hwseq_xfer() - Execute FAST_SPI flash transfer

Should we just mention this is flash transfer using hardware
sequencer, instead of FAST_SPI?

> + *
> + * This waits until complete or timeout
> + *
> + * @regs: SPI registers
> + * @hsfsts_cycle: Cycle type (enum hsfsts_cycle_t)
> + * @offset: Offset to access
> + * @len: Number of bytes to transfer (can be 0)
> + * @return 9 if OK, -EIO on flash-cycle error (FCERR), -EPERM on access error

0 if OK

> + *     (AEL), -ETIMEDOUT on timeout
> + */
> +static int exec_sync_hwseq_xfer(struct fast_spi_regs *regs, uint hsfsts_cycle,
> +                               uint offset, uint len)
> +{
> +       start_hwseq_xfer(regs, hsfsts_cycle, offset, len);
> +
> +       return wait_for_hwseq_xfer(regs, offset);
> +}
> +
> +static int ich_spi_exec_op_hwseq(struct spi_slave *slave,
> +                                const struct spi_mem_op *op)
> +{
> +       struct spi_flash *flash = dev_get_uclass_priv(slave->dev);
> +       struct udevice *bus = dev_get_parent(slave->dev);
> +       struct ich_spi_priv *priv = dev_get_priv(bus);
> +       struct fast_spi_regs *regs = priv->base;
> +       uint page_size;
> +       uint offset;
> +       int cycle;
> +       uint len;
> +       bool out;
> +       int ret;
> +       u8 *buf;
> +
> +       offset = op->addr.val;
> +       len = op->data.nbytes;
> +
> +       switch (op->cmd.opcode) {
> +       case SPINOR_OP_RDID:
> +               cycle = HSFSTS_CYCLE_RDID;
> +               break;
> +       case SPINOR_OP_READ_FAST:
> +               cycle = HSFSTS_CYCLE_READ;
> +               break;
> +       case SPINOR_OP_PP:
> +               cycle = HSFSTS_CYCLE_WRITE;
> +               break;
> +       case SPINOR_OP_WREN:
> +               /* Nothing needs to be done */
> +               return 0;
> +       case SPINOR_OP_WRSR:
> +               cycle = HSFSTS_CYCLE_WR_STATUS;
> +               break;
> +       case SPINOR_OP_RDSR:
> +               cycle = HSFSTS_CYCLE_RD_STATUS;
> +               break;
> +       case SPINOR_OP_WRDI:
> +               return 0;  /* ignore */
> +       case SPINOR_OP_BE_4K:
> +               cycle = HSFSTS_CYCLE_4K_ERASE;
> +               while (len) {
> +                       uint xfer_len = 0x1000;
> +
> +                       ret = exec_sync_hwseq_xfer(regs, cycle, offset, 0);
> +                       if (ret)
> +                               return ret;
> +                       offset += xfer_len;
> +                       len -= xfer_len;
> +               }
> +               return 0;
> +       default:
> +               debug("Unknown cycle %x\n", op->cmd.opcode);
> +               return -EINVAL;
> +       };
> +
> +       out = op->data.dir == SPI_MEM_DATA_OUT;
> +       buf = out ? (u8 *)op->data.buf.out : op->data.buf.in;
> +       page_size = flash->page_size ? : 256;
> +
> +       while (len) {
> +               uint xfer_len = get_xfer_len(offset, len, page_size);
> +
> +               if (out)
> +                       fill_xfer_fifo(regs, buf, xfer_len);
> +
> +               ret = exec_sync_hwseq_xfer(regs, cycle, offset, xfer_len);
> +               if (ret)
> +                       return ret;
> +
> +               if (!out)
> +                       drain_xfer_fifo(regs, buf, xfer_len);
> +
> +               offset += xfer_len;
> +               buf += xfer_len;
> +               len -= xfer_len;
> +       }
> +
> +       return 0;
> +}
> +
> +static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
> +{
> +       struct udevice *bus = dev_get_parent(slave->dev);
> +       struct ich_spi_platdata *plat = dev_get_platdata(bus);
> +       int ret;
> +
> +       bootstage_start(BOOTSTAGE_ID_ACCUM_SPI, "fast_spi");
> +       if (plat->hwseq)
> +               ret = ich_spi_exec_op_hwseq(slave, op);
> +       else
> +               ret = ich_spi_exec_op_swseq(slave, op);
> +       bootstage_accum(BOOTSTAGE_ID_ACCUM_SPI);
> +
> +       return ret;
> +}
> +
>  static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
>  {
>         unsigned int page_offset;
> @@ -585,9 +780,11 @@ static int ich_spi_child_pre_probe(struct udevice *dev)
>
>         /*
>          * Yes this controller can only write a small number of bytes at
> -        * once! The limit is typically 64 bytes.
> +        * once! The limit is typically 64 bytes. For hardware sequencing a
> +        * a loop is used to get around this.
>          */
> -       slave->max_write_size = priv->databytes;
> +       if (!plat->hwseq)
> +               slave->max_write_size = priv->databytes;
>         /*
>          * ICH 7 SPI controller only supports array read command
>          * and byte program command for SST flash
> @@ -606,10 +803,12 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
>         plat->ich_version = dev_get_driver_data(dev);
>         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
>         pch_get_spi_base(dev->parent, &plat->mmio_base);
> +       plat->hwseq = dev_read_u32_default(dev, "intel,hardware-seq", 0);
>  #else
>         plat->ich_version = ICHV_APL;
>         plat->mmio_base = plat->dtplat.early_regs[0];
>         plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> +       plat->hwseq = plat->dtplat.intel_hardware_seq;
>  #endif
>         debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
>
> diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
> index 623b2c547a6..c7cf37b9321 100644
> --- a/drivers/spi/ich.h
> +++ b/drivers/spi/ich.h
> @@ -163,6 +163,45 @@ struct spi_trans {
>
>  #define ICH_BOUNDARY   0x1000
>
> +#define HSFSTS_FDBC_SHIFT      24
> +#define HSFSTS_FDBC_MASK       (0x3f << HSFSTS_FDBC_SHIFT)
> +#define HSFSTS_WET             BIT(21)
> +#define HSFSTS_FCYCLE_SHIFT    17
> +#define HSFSTS_FCYCLE_MASK     (0xf << HSFSTS_FCYCLE_SHIFT)
> +
> +/* Supported flash cycle types */
> +enum hsfsts_cycle_t {
> +       HSFSTS_CYCLE_READ       = 0,
> +       HSFSTS_CYCLE_WRITE      = 2,
> +       HSFSTS_CYCLE_4K_ERASE,
> +       HSFSTS_CYCLE_64K_ERASE,
> +       HSFSTS_CYCLE_RDSFDP,
> +       HSFSTS_CYCLE_RDID,
> +       HSFSTS_CYCLE_WR_STATUS,
> +       HSFSTS_CYCLE_RD_STATUS,
> +};
> +
> +#define HSFSTS_FGO             BIT(16)
> +#define HSFSTS_FLOCKDN         BIT(15)
> +#define HSFSTS_FDV             BIT(14)
> +#define HSFSTS_FDOPSS          BIT(13)
> +#define HSFSTS_WRSDIS          BIT(11)
> +#define HSFSTS_SAF_CE          BIT(8)
> +#define HSFSTS_SAF_ACTIVE      BIT(7)
> +#define HSFSTS_SAF_LE          BIT(6)
> +#define HSFSTS_SCIP            BIT(5)
> +#define HSFSTS_SAF_DLE         BIT(4)
> +#define HSFSTS_SAF_ERROR       BIT(3)
> +#define HSFSTS_AEL             BIT(2)
> +#define HSFSTS_FCERR           BIT(1)
> +#define HSFSTS_FDONE           BIT(0)
> +#define HSFSTS_W1C_BITS                0xff
> +
> +/* Maximum bytes of data that can fit in FDATAn (0x10) registers */
> +#define SPIBAR_FDATA_FIFO_SIZE         0x40
> +
> +#define SPIBAR_HWSEQ_XFER_TIMEOUT_MS   5000
> +
>  enum ich_version {
>         ICHV_7,
>         ICHV_9,
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support Simon Glass
@ 2019-11-19 14:52   ` Bin Meng
  2019-11-21 13:50     ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:52 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> In TPL we want to reduce code size and support running with CONFIG_PCI
> disabled. Add special code to handle this using a fixed BAR programmed
> into the SPI on boot. Also cache the SPI flash to speed up boot.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 42 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index ec0f77f6e40..daa69c25a3a 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -19,8 +19,10 @@
>  #include <spi.h>
>  #include <spi_flash.h>
>  #include <spi-mem.h>
> +#include <spl.h>
>  #include <asm/fast_spi.h>
>  #include <asm/io.h>
> +#include <asm/mtrr.h>
>
>  #include "ich.h"
>
> @@ -114,6 +116,8 @@ static bool ich9_can_do_33mhz(struct udevice *dev)
>  {
>         u32 fdod, speed;
>
> +       if (!CONFIG_IS_ENABLED(PCI))
> +               return false;
>         /* Observe SPI Descriptor Component Section 0 */
>         dm_pci_write_config32(dev->parent, 0xb0, 0x1000);
>
> @@ -705,6 +709,15 @@ static int ich_init_controller(struct udevice *dev,
>                                struct ich_spi_platdata *plat,
>                                struct ich_spi_priv *ctlr)
>  {
> +       if (spl_phase() == PHASE_TPL) {
> +               struct ich_spi_platdata *plat = dev_get_platdata(dev);
> +               int ret;
> +
> +               ret = fast_spi_early_init(plat->bdf, plat->mmio_base);

Can we move the fast_spi_early_init() contents to ich_spi_probe(),
where the bios_cntl register is programmed to disable the write
protect for ICH_V7? This helps reading as it's disabling write
protect, but for different ICH SPI variants.

> +               if (ret)
> +                       return ret;
> +       }
> +
>         ctlr->base = (void *)plat->mmio_base;
>         if (plat->ich_version == ICHV_7) {
>                 struct ich7_spi_regs *ich7_spi = ctlr->base;
> @@ -753,6 +766,25 @@ static int ich_init_controller(struct udevice *dev,
>         return 0;
>  }
>
> +static int ich_cache_bios_region(struct udevice *dev)
> +{
> +       ulong map_base;
> +       uint map_size;
> +       uint offset;
> +       ulong base;
> +       int ret;
> +
> +       ret = ich_get_mmap_bus(dev, &map_base, &map_size, &offset);
> +       if (ret)
> +               return ret;
> +
> +       base = (4ULL << 30) - map_size;
> +       mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
> +       log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
> +
> +       return 0;
> +}
> +
>  static int ich_spi_probe(struct udevice *dev)
>  {
>         struct ich_spi_platdata *plat = dev_get_platdata(dev);
> @@ -766,10 +798,16 @@ static int ich_spi_probe(struct udevice *dev)
>         if (ret)
>                 return ret;
>
> -       ret = ich_protect_lockdown(dev);
> -       if (ret)
> -               return ret;
> -
> +       if (spl_phase() == PHASE_TPL) {
> +               /* Cache the BIOS to speed things up */
> +               ret = ich_cache_bios_region(dev);
> +               if (ret)
> +                       return ret;
> +       } else {
> +               ret = ich_protect_lockdown(dev);
> +               if (ret)
> +                       return ret;
> +       }
>         priv->cur_speed = priv->max_speed;
>
>         return 0;
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 087/108] spi: ich: Add Apollolake support
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 087/108] spi: ich: Add Apollolake support Simon Glass
@ 2019-11-19 14:52   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:52 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add support for Apollolake to the ICH driver. This involves adjusting the
> mmio address and skipping setting of the bbar.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/ich.c | 19 ++++++++++++++-----
>  drivers/spi/ich.h |  1 +
>  2 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index daa69c25a3a..77ab951edc1 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -105,10 +105,12 @@ static void ich_set_bbar(struct ich_spi_priv *ctlr, uint32_t minaddr)
>         const uint32_t bbar_mask = 0x00ffff00;
>         uint32_t ichspi_bbar;
>
> -       minaddr &= bbar_mask;
> -       ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
> -       ichspi_bbar |= minaddr;
> -       ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
> +       if (ctlr->bbar) {
> +               minaddr &= bbar_mask;
> +               ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
> +               ichspi_bbar |= minaddr;
> +               ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
> +       }
>  }
>
>  /* @return 1 if the SPI flash supports the 33MHz speed */
> @@ -748,6 +750,7 @@ static int ich_init_controller(struct udevice *dev,
>                 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
>                 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
>                 ctlr->pr = &ich9_spi->pr[0];
> +       } else if (plat->ich_version == ICHV_APL) {
>         } else {
>                 debug("ICH SPI: Unrecognised ICH version %d\n",
>                       plat->ich_version);
> @@ -871,7 +874,12 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
>  #if !CONFIG_IS_ENABLED(OF_PLATDATA)
>         plat->ich_version = dev_get_driver_data(dev);
>         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> -       pch_get_spi_base(dev->parent, &plat->mmio_base);
> +       if (plat->ich_version == ICHV_APL) {
> +               plat->mmio_base = dm_pci_read_bar32(dev, 0);
> +       } else  {
> +               /* SBASE is similar */
> +               pch_get_spi_base(dev->parent, &plat->mmio_base);

priv->pch, instead of dev->parent?

> +       }
>         plat->hwseq = dev_read_u32_default(dev, "intel,hardware-seq", 0);
>  #else
>         plat->ich_version = ICHV_APL;
> @@ -905,6 +913,7 @@ static const struct dm_spi_ops ich_spi_ops = {
>  static const struct udevice_id ich_spi_ids[] = {
>         { .compatible = "intel,ich7-spi", ICHV_7 },
>         { .compatible = "intel,ich9-spi", ICHV_9 },
> +       { .compatible = "intel,fast-spi", ICHV_APL },
>         { }
>  };
>
> diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
> index c7cf37b9321..d7f1ffdf37d 100644
> --- a/drivers/spi/ich.h
> +++ b/drivers/spi/ich.h
> @@ -205,6 +205,7 @@ enum hsfsts_cycle_t {
>  enum ich_version {
>         ICHV_7,
>         ICHV_9,
> +       ICHV_APL,
>  };
>
>  struct ich_spi_priv {
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 088/108] mtd: spi: Export spi_flash_std_probe()
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 088/108] mtd: spi: Export spi_flash_std_probe() Simon Glass
@ 2019-11-19 14:52   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> With of-platdata we need to create drivers for particular chips, or at
> least drivers that are separate from the standard code, since C structures
> are created by dtoc which are private to that driver.
>
> To avoid duplicating the probing code, export this probe function for use
> by these drivers.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/mtd/spi/sf_probe.c |  2 +-
>  include/spi_flash.h        | 12 ++++++++++++
>  2 files changed, 13 insertions(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 089/108] x86: apollolake: Add basic IO addresses
  2019-10-21  3:38 ` [U-Boot] [PATCH v3 089/108] x86: apollolake: Add basic IO addresses Simon Glass
@ 2019-11-19 14:52   ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-19 14:52 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>
> Add some fixed IO and mmap addresses for use in the device tree and with
> some early-init code.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/include/asm/arch-apollolake/iomap.h | 28 ++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>  create mode 100644 arch/x86/include/asm/arch-apollolake/iomap.h
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function
  2019-11-19 13:53   ` Bin Meng
@ 2019-11-19 17:53     ` Simon Glass
  2019-11-20 12:55       ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-11-19 17:53 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, 19 Nov 2019 at 05:53, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Reduce the size of the probe function but putting this code into its own
> > function.
> >
>
> It's unclear to me why this brings any benefit? The size of the probe
> function indeed is reduced, but whole file size does not change, no?

It's just that it gives the code a name and groups it in a function.
It is normally better to have shorter functions and this one seemed to
be getting a bit long and unfocussed.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata
  2019-11-19 14:36   ` Bin Meng
@ 2019-11-19 17:53     ` Simon Glass
  2019-11-20 12:52       ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-11-19 17:53 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, 19 Nov 2019 at 06:36, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > It is useful to store the mmio base in platdata. It reduces the amount of
> > casting needed. Update the code and move the struct to the C file at the
> > same time, as we will need to use with of-platdata.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  drivers/spi/ich.c | 27 +++++++++++++--------------
> >  drivers/spi/ich.h |  5 -----
> >  2 files changed, 13 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > index e2bc77bbd58..7f73f096ecb 100644
> > --- a/drivers/spi/ich.c
> > +++ b/drivers/spi/ich.c
> > @@ -27,6 +27,12 @@
> >  #define debug_trace(x, args...)
> >  #endif
> >
> > +struct ich_spi_platdata {
> > +       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > +       bool lockdown;                  /* lock down controller settings? */
> > +       ulong mmio_base;                /* Base of MMIO registers */
> > +};
> > +
> >  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> >  {
> >         u8 value = readb(priv->base + reg);
> > @@ -466,16 +472,9 @@ static int ich_init_controller(struct udevice *dev,
> >                                struct ich_spi_platdata *plat,
> >                                struct ich_spi_priv *ctlr)
> >  {
> > -       ulong sbase_addr;
> > -       void *sbase;
> > -
> > -       /* SBASE is similar */
> > -       pch_get_spi_base(dev->parent, &sbase_addr);
> > -       sbase = (void *)sbase_addr;
> > -       debug("%s: sbase=%p\n", __func__, sbase);
> > -
> > +       ctlr->base = (void *)plat->mmio_base;
> >         if (plat->ich_version == ICHV_7) {
> > -               struct ich7_spi_regs *ich7_spi = sbase;
> > +               struct ich7_spi_regs *ich7_spi = ctlr->base;
> >
> >                 ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
> >                 ctlr->menubytes = sizeof(ich7_spi->opmenu);
> > @@ -487,9 +486,8 @@ static int ich_init_controller(struct udevice *dev,
> >                 ctlr->control = offsetof(struct ich7_spi_regs, spic);
> >                 ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
> >                 ctlr->preop = offsetof(struct ich7_spi_regs, preop);
> > -               ctlr->base = ich7_spi;
> >         } else if (plat->ich_version == ICHV_9) {
> > -               struct ich9_spi_regs *ich9_spi = sbase;
> > +               struct ich9_spi_regs *ich9_spi = ctlr->base;
> >
> >                 ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
> >                 ctlr->menubytes = sizeof(ich9_spi->opmenu);
> > @@ -504,7 +502,6 @@ static int ich_init_controller(struct udevice *dev,
> >                 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
> >                 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
> >                 ctlr->pr = &ich9_spi->pr[0];
> > -               ctlr->base = ich9_spi;
> >         } else {
> >                 debug("ICH SPI: Unrecognised ICH version %d\n",
> >                       plat->ich_version);
> > @@ -515,8 +512,8 @@ static int ich_init_controller(struct udevice *dev,
> >         ctlr->max_speed = 20000000;
> >         if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
> >                 ctlr->max_speed = 33000000;
> > -       debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
> > -             plat->ich_version, ctlr->base, ctlr->max_speed);
> > +       debug("ICH SPI: Version ID %d detected at %lx, speed %ld\n",
> > +             plat->ich_version, plat->mmio_base, ctlr->max_speed);
> >
> >         ich_set_bbar(ctlr, 0);
> >
> > @@ -601,6 +598,8 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
> >         plat->ich_version = dev_get_driver_data(dev);
> >         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> >
> > +       pch_get_spi_base(dev->parent, &plat->mmio_base);
>
> In patch [77], spi: ich: Move the protection/lockdown code into a
> function, we already removed the assumption of dev->parent, but used
> priv->pch for the PCH device.

Yes, this should use priv->pch, I think.

>
> > +
> >         return 0;
> >  }
> >
> > diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
> > index 77057878a5d..623b2c547a6 100644
> > --- a/drivers/spi/ich.h
> > +++ b/drivers/spi/ich.h
> > @@ -168,11 +168,6 @@ enum ich_version {
> >         ICHV_9,
> >  };
> >
> > -struct ich_spi_platdata {
> > -       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > -       bool lockdown;                  /* lock down controller settings? */
> > -};
>
> I don't understand why moving this struct to C file?

We need to add of-platdata to this struct and don't want to do that in
a header file. It  ends up begin:

struct ich_spi_platdata {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
   struct dtd... ...;
#endif
       enum ich_version ich_version;   /* Controller version, 7 or 9 */
...
}

All structs that use of-platdata should be in C files, I think.

>
> > -
> >  struct ich_spi_priv {
> >         int opmenu;
> >         int menubytes;
> > --
Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi
  2019-11-19 14:36   ` Bin Meng
@ 2019-11-19 17:53     ` Simon Glass
  2019-11-20 12:48       ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-11-19 17:53 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, 19 Nov 2019 at 06:36, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > The Intel Fast SPI interface is similar to ICH. Add of-platdata support
> > for this using the "intel,fast-spi" compatible string.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  drivers/spi/ich.c | 17 ++++++++++++++---
> >  1 file changed, 14 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > index b28f3423584..ae3bff36bba 100644
> > --- a/drivers/spi/ich.c
> > +++ b/drivers/spi/ich.c
> > @@ -10,6 +10,7 @@
> >  #include <common.h>
> >  #include <div64.h>
> >  #include <dm.h>
> > +#include <dt-structs.h>
> >  #include <errno.h>
> >  #include <malloc.h>
> >  #include <pch.h>
> > @@ -28,9 +29,13 @@
> >  #endif
> >
> >  struct ich_spi_platdata {
> > +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> > +       struct dtd_intel_fast_spi dtplat;
> > +#endif
> >         enum ich_version ich_version;   /* Controller version, 7 or 9 */
> >         bool lockdown;                  /* lock down controller settings? */
> >         ulong mmio_base;                /* Base of MMIO registers */
> > +       pci_dev_t bdf;                  /* PCI address used by of-platdata */
> >  };
> >
> >  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> > @@ -597,10 +602,16 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
> >  {
> >         struct ich_spi_platdata *plat = dev_get_platdata(dev);
> >
> > +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> >         plat->ich_version = dev_get_driver_data(dev);
> >         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> > -
> >         pch_get_spi_base(dev->parent, &plat->mmio_base);
> > +#else
> > +       plat->ich_version = ICHV_APL;
>
> I don't think the ICH_VERSION is something that is controlled via OF_PLATDATA.

Well, the fact that we are using dtd_intel_fast_spi means that the
compatible string is intel,fast-spi, so that's why we set this version
variable. The older SPI-controller versions don't actually support
of-platdata, so this is safe.

>
> > +       plat->mmio_base = plat->dtplat.early_regs[0];
> > +       plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> > +#endif
> > +       debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
> >
> >         return 0;
> >  }
> > @@ -628,8 +639,8 @@ static const struct udevice_id ich_spi_ids[] = {
> >         { }
> >  };
> >
> > -U_BOOT_DRIVER(ich_spi) = {
> > -       .name   = "ich_spi",
> > +U_BOOT_DRIVER(intel_fast_spi) = {
>
> Why changing the driver name?

So that of-platdata will create a U_BOOT_DEVICE() for it and it will
be bound. Otherwise the name will not match and the device is ignored.

I will update the commit message.

>
> > +       .name   = "intel_fast_spi",
> >         .id     = UCLASS_SPI,
> >         .of_match = ich_spi_ids,
> >         .ops    = &ich_spi_ops,
> > --
>
> Regards,
> Bin

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default
  2019-11-19 13:33   ` Bin Meng
@ 2019-11-20  5:22     ` Vignesh Raghavendra
  2019-11-21 13:50       ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Vignesh Raghavendra @ 2019-11-20  5:22 UTC (permalink / raw)
  To: u-boot

Hi,

On 19/11/19 7:03 PM, Bin Meng wrote:
> +Vignesh
> 
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
>>
>> We don't normally need this on x86 unless the size of SPI flash devices is
>> larger than 16MB. This can be enabled by particular SoCs as needed, since
>> it adds to code size.
>>
>> Drop the default enabling of this option on x86.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v3: None
>> Changes in v2: None
>>
>>  drivers/spi/Kconfig | 1 -
>>  1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index b8ca2bdedd5..320baeeb3eb 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -125,7 +125,6 @@ config FSL_DSPI
>>
>>  config ICH_SPI
>>         bool "Intel ICH SPI driver"
>> -       imply SPI_FLASH_BAR
> 
> This was added via:
> 
> commit 6d82517836418f984b7b4c05cf1427d7b49b1169
> Author: Vignesh R <vigneshr@ti.com>
> Date:   Tue Feb 5 11:29:28 2019 +0530
> 
>     configs: Don't use SPI_FLASH_BAR as default
> 
>     Now that new SPI NOR layer uses stateless 4 byte opcodes by default,
>     don't enable SPI_FLASH_BAR. For SPI controllers that cannot support
>     4-byte addressing, (stm32_qspi.c, fsl_qspi.c, mtk_qspi.c, ich.c,
>     renesas_rpc_spi.c) add an imply clause to enable SPI_FLASH_BAR so as to
>     not break functionality.
> 
> The commit message says: SPI_FLASH_BAR was added so as to not break
> functionality.
> 

At the time of introducing new SPI NOR layer, I found that (by code
inspection) ich.c did  not support 4 byte addressing. Hence, "imply
SPI_FLASH_BAR" was added for ich.c driver.
But if driver has been improved to support 4 byte addressing or if there
is no plan to support flashes > 16MiB by default, then it should be okay
to remove SPI_FLASH_BAR.

> I don't have board to test right now. Vignesh could you please have a
> review? Thanks!
> 
>>         help
>>           Enable the Intel ICH SPI driver. This driver can be used to
>>           access the SPI NOR flash on platforms embedding this Intel
>> --
> 
> Regards,
> Bin
> 

-- 
Regards
Vignesh

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi
  2019-11-19 17:53     ` Simon Glass
@ 2019-11-20 12:48       ` Bin Meng
  2019-11-21 13:50         ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-20 12:48 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Nov 20, 2019 at 1:53 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Tue, 19 Nov 2019 at 06:36, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > The Intel Fast SPI interface is similar to ICH. Add of-platdata support
> > > for this using the "intel,fast-spi" compatible string.
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > ---
> > >
> > > Changes in v3: None
> > > Changes in v2: None
> > >
> > >  drivers/spi/ich.c | 17 ++++++++++++++---
> > >  1 file changed, 14 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > > index b28f3423584..ae3bff36bba 100644
> > > --- a/drivers/spi/ich.c
> > > +++ b/drivers/spi/ich.c
> > > @@ -10,6 +10,7 @@
> > >  #include <common.h>
> > >  #include <div64.h>
> > >  #include <dm.h>
> > > +#include <dt-structs.h>
> > >  #include <errno.h>
> > >  #include <malloc.h>
> > >  #include <pch.h>
> > > @@ -28,9 +29,13 @@
> > >  #endif
> > >
> > >  struct ich_spi_platdata {
> > > +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> > > +       struct dtd_intel_fast_spi dtplat;
> > > +#endif
> > >         enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > >         bool lockdown;                  /* lock down controller settings? */
> > >         ulong mmio_base;                /* Base of MMIO registers */
> > > +       pci_dev_t bdf;                  /* PCI address used by of-platdata */
> > >  };
> > >
> > >  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> > > @@ -597,10 +602,16 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
> > >  {
> > >         struct ich_spi_platdata *plat = dev_get_platdata(dev);
> > >
> > > +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> > >         plat->ich_version = dev_get_driver_data(dev);
> > >         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> > > -
> > >         pch_get_spi_base(dev->parent, &plat->mmio_base);
> > > +#else
> > > +       plat->ich_version = ICHV_APL;
> >
> > I don't think the ICH_VERSION is something that is controlled via OF_PLATDATA.
>
> Well, the fact that we are using dtd_intel_fast_spi means that the
> compatible string is intel,fast-spi, so that's why we set this version
> variable. The older SPI-controller versions don't actually support
> of-platdata, so this is safe.
>

What if we have another platform that uses OF_PLATDATA but is not
ICHV_APL? How do we distinguish that?

> >
> > > +       plat->mmio_base = plat->dtplat.early_regs[0];
> > > +       plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> > > +#endif
> > > +       debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
> > >
> > >         return 0;
> > >  }
> > > @@ -628,8 +639,8 @@ static const struct udevice_id ich_spi_ids[] = {
> > >         { }
> > >  };
> > >
> > > -U_BOOT_DRIVER(ich_spi) = {
> > > -       .name   = "ich_spi",
> > > +U_BOOT_DRIVER(intel_fast_spi) = {
> >
> > Why changing the driver name?
>
> So that of-platdata will create a U_BOOT_DEVICE() for it and it will
> be bound. Otherwise the name will not match and the device is ignored.
>

Could we avoid renaming the driver, ie: reusing the same "ich_spi" name?

> I will update the commit message.
>
> >
> > > +       .name   = "intel_fast_spi",
> > >         .id     = UCLASS_SPI,
> > >         .of_match = ich_spi_ids,
> > >         .ops    = &ich_spi_ops,
> > > --

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata
  2019-11-19 17:53     ` Simon Glass
@ 2019-11-20 12:52       ` Bin Meng
  2019-11-21 13:50         ` Simon Glass
  0 siblings, 1 reply; 201+ messages in thread
From: Bin Meng @ 2019-11-20 12:52 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Nov 20, 2019 at 1:53 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Tue, 19 Nov 2019 at 06:36, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > It is useful to store the mmio base in platdata. It reduces the amount of
> > > casting needed. Update the code and move the struct to the C file at the
> > > same time, as we will need to use with of-platdata.
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > ---
> > >
> > > Changes in v3: None
> > > Changes in v2: None
> > >
> > >  drivers/spi/ich.c | 27 +++++++++++++--------------
> > >  drivers/spi/ich.h |  5 -----
> > >  2 files changed, 13 insertions(+), 19 deletions(-)
> > >
> > > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > > index e2bc77bbd58..7f73f096ecb 100644
> > > --- a/drivers/spi/ich.c
> > > +++ b/drivers/spi/ich.c
> > > @@ -27,6 +27,12 @@
> > >  #define debug_trace(x, args...)
> > >  #endif
> > >
> > > +struct ich_spi_platdata {
> > > +       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > > +       bool lockdown;                  /* lock down controller settings? */
> > > +       ulong mmio_base;                /* Base of MMIO registers */
> > > +};
> > > +
> > >  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> > >  {
> > >         u8 value = readb(priv->base + reg);
> > > @@ -466,16 +472,9 @@ static int ich_init_controller(struct udevice *dev,
> > >                                struct ich_spi_platdata *plat,
> > >                                struct ich_spi_priv *ctlr)
> > >  {
> > > -       ulong sbase_addr;
> > > -       void *sbase;
> > > -
> > > -       /* SBASE is similar */
> > > -       pch_get_spi_base(dev->parent, &sbase_addr);
> > > -       sbase = (void *)sbase_addr;
> > > -       debug("%s: sbase=%p\n", __func__, sbase);
> > > -
> > > +       ctlr->base = (void *)plat->mmio_base;
> > >         if (plat->ich_version == ICHV_7) {
> > > -               struct ich7_spi_regs *ich7_spi = sbase;
> > > +               struct ich7_spi_regs *ich7_spi = ctlr->base;
> > >
> > >                 ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
> > >                 ctlr->menubytes = sizeof(ich7_spi->opmenu);
> > > @@ -487,9 +486,8 @@ static int ich_init_controller(struct udevice *dev,
> > >                 ctlr->control = offsetof(struct ich7_spi_regs, spic);
> > >                 ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
> > >                 ctlr->preop = offsetof(struct ich7_spi_regs, preop);
> > > -               ctlr->base = ich7_spi;
> > >         } else if (plat->ich_version == ICHV_9) {
> > > -               struct ich9_spi_regs *ich9_spi = sbase;
> > > +               struct ich9_spi_regs *ich9_spi = ctlr->base;
> > >
> > >                 ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
> > >                 ctlr->menubytes = sizeof(ich9_spi->opmenu);
> > > @@ -504,7 +502,6 @@ static int ich_init_controller(struct udevice *dev,
> > >                 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
> > >                 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
> > >                 ctlr->pr = &ich9_spi->pr[0];
> > > -               ctlr->base = ich9_spi;
> > >         } else {
> > >                 debug("ICH SPI: Unrecognised ICH version %d\n",
> > >                       plat->ich_version);
> > > @@ -515,8 +512,8 @@ static int ich_init_controller(struct udevice *dev,
> > >         ctlr->max_speed = 20000000;
> > >         if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
> > >                 ctlr->max_speed = 33000000;
> > > -       debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
> > > -             plat->ich_version, ctlr->base, ctlr->max_speed);
> > > +       debug("ICH SPI: Version ID %d detected at %lx, speed %ld\n",
> > > +             plat->ich_version, plat->mmio_base, ctlr->max_speed);
> > >
> > >         ich_set_bbar(ctlr, 0);
> > >
> > > @@ -601,6 +598,8 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
> > >         plat->ich_version = dev_get_driver_data(dev);
> > >         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> > >
> > > +       pch_get_spi_base(dev->parent, &plat->mmio_base);
> >
> > In patch [77], spi: ich: Move the protection/lockdown code into a
> > function, we already removed the assumption of dev->parent, but used
> > priv->pch for the PCH device.
>
> Yes, this should use priv->pch, I think.
>
> >
> > > +
> > >         return 0;
> > >  }
> > >
> > > diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
> > > index 77057878a5d..623b2c547a6 100644
> > > --- a/drivers/spi/ich.h
> > > +++ b/drivers/spi/ich.h
> > > @@ -168,11 +168,6 @@ enum ich_version {
> > >         ICHV_9,
> > >  };
> > >
> > > -struct ich_spi_platdata {
> > > -       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > > -       bool lockdown;                  /* lock down controller settings? */
> > > -};
> >
> > I don't understand why moving this struct to C file?
>
> We need to add of-platdata to this struct and don't want to do that in
> a header file. It  ends up begin:
>
> struct ich_spi_platdata {
> #if CONFIG_IS_ENABLED(OF_PLATDATA)
>    struct dtd... ...;
> #endif
>        enum ich_version ich_version;   /* Controller version, 7 or 9 */
> ...
> }
>
> All structs that use of-platdata should be in C files, I think.
>

Is this hard requirement for drivers with of-platdata? Maybe we need
update of-plat.rst to better document this rule.

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function
  2019-11-19 17:53     ` Simon Glass
@ 2019-11-20 12:55       ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-20 12:55 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Nov 20, 2019 at 1:53 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Tue, 19 Nov 2019 at 05:53, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Reduce the size of the probe function but putting this code into its own
> > > function.
> > >
> >
> > It's unclear to me why this brings any benefit? The size of the probe
> > function indeed is reduced, but whole file size does not change, no?
>
> It's just that it gives the code a name and groups it in a function.
> It is normally better to have shorter functions and this one seemed to
> be getting a bit long and unfocussed.
>

OK, I think I misunderstood it. I thought you wanted to reduce the
code size for TPL when I saw the commit message, but it didn't reduce
code size at all.

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass
  2019-11-04  8:02   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Mon, 4 Nov 2019 at 00:03, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Intel x86 SoCs have a power manager/controller which handles several
> > power-related aspects of the platform. Add a uclass for this, with a few
> > useful operations.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > - Rename power-mgr uclass to acpi-pmc
> >
> > Changes in v2: None
> >
> >  drivers/power/Kconfig                    |   2 +
> >  drivers/power/acpi_pmc/Kconfig           |  25 +++
> >  drivers/power/acpi_pmc/Makefile          |   5 +
> >  drivers/power/acpi_pmc/acpi-pmc-uclass.c | 191 +++++++++++++++++++++++
> >  include/dm/uclass-id.h                   |   1 +
> >  include/power/acpi_pmc.h                 | 185 ++++++++++++++++++++++
> >  6 files changed, 409 insertions(+)
> >  create mode 100644 drivers/power/acpi_pmc/Kconfig
> >  create mode 100644 drivers/power/acpi_pmc/Makefile
> >  create mode 100644 drivers/power/acpi_pmc/acpi-pmc-uclass.c
> >  create mode 100644 include/power/acpi_pmc.h
> >
[..]

> > +int pmc_init(struct udevice *dev)
> > +{
> > +       const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
> > +       int ret;
> > +
> > +       pmc_fill_pm_reg_info(dev);
> > +       if (!ops->init)
> > +               return -ENOSYS;
> > +
> > +       ret = ops->init(dev);
> > +       if (ret)
> > +               return log_msg_ret("Failed to init pmc", ret);
> > +
> > +#ifdef DEBUG
> > +       pmc_dump_info(dev);
> > +#endif
> > +
> > +       return 0;
> > +}
>
> I wonder shouldn't this be covered by the probe() method?

This is called at present from SPL to read information that is not
needed in TPL. In effect the PMC is mostly just used for info in TPL,
so we don't want to

We could have a check in the probe() function and do different things
in TPL, but at the moment I feel that it is worth having an 'init'
function which actually sets things up when needed.

[..]

>
> [snip]
>
> Regards,
> Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass
  2019-11-04  8:23   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Mon, 4 Nov 2019 at 00:23, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > The Primary-to-Sideband bus (P2SB) is used to access various peripherals
> > through memory-mapped I/O in a large chunk of PCI space. The space is
> > segmented into different channels and peripherals are accessed by
> > device-specific means within those channels. Devices should be added in
> > the device tree as subnodes of the p2sb.
> >
> > This adds a uclass and enables it for sandbox.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  configs/sandbox_defconfig     |   1 +
> >  configs/sandbox_spl_defconfig |   1 +
> >  drivers/misc/Kconfig          |  33 ++++++
> >  drivers/misc/Makefile         |   1 +
> >  drivers/misc/p2sb-uclass.c    | 209 ++++++++++++++++++++++++++++++++++
> >  include/dm/uclass-id.h        |   1 +
> >  include/p2sb.h                | 127 +++++++++++++++++++++
> >  7 files changed, 373 insertions(+)
> >  create mode 100644 drivers/misc/p2sb-uclass.c
> >  create mode 100644 include/p2sb.h
> >
> > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> > index 20ebc68997b..f8b78b8d7e1 100644
> > --- a/configs/sandbox_defconfig
> > +++ b/configs/sandbox_defconfig
> > @@ -150,6 +150,7 @@ CONFIG_PCI=y
> >  CONFIG_DM_PCI=y
> >  CONFIG_DM_PCI_COMPAT=y
> >  CONFIG_PCI_SANDBOX=y
> > +CONFIG_P2SB=y
> >  CONFIG_PHY=y
> >  CONFIG_PHY_SANDBOX=y
> >  CONFIG_PINCTRL=y
> > diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
> > index 409b8a38d5e..c49e05ec319 100644
> > --- a/configs/sandbox_spl_defconfig
> > +++ b/configs/sandbox_spl_defconfig
> > @@ -135,6 +135,7 @@ CONFIG_PCI=y
> >  CONFIG_DM_PCI=y
> >  CONFIG_DM_PCI_COMPAT=y
> >  CONFIG_PCI_SANDBOX=y
> > +CONFIG_P2SB=y
> >  CONFIG_PHY=y
> >  CONFIG_PHY_SANDBOX=y
> >  CONFIG_PINCTRL=y
> > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> > index ba50893b432..1ed2e5d4aa2 100644
> > --- a/drivers/misc/Kconfig
> > +++ b/drivers/misc/Kconfig
> > @@ -217,6 +217,39 @@ config NUVOTON_NCT6102D
> >           disable the legacy UART, the watchdog or other devices
> >           in the Nuvoton Super IO chips on X86 platforms.
> >
> > +config P2SB
> > +       bool "Intel Primary-to-Sideband Bus"
> > +       depends on X86 || SANDBOX
> > +       help
> > +         This enables support for the Intel Primary-to-Sideband bus,
> > +         abbreviated to P2SB. The P2SB is used to access various peripherals
> > +         such as eSPI, GPIO, through memory-mapped I/O in a large chunk of PCI
> > +         space. The space is segmented into different channels and peripherals
> > +         are accessed by device-specific means within those channels. Devices
> > +         should be added in the device tree as subnodes of the P2SB. A
> > +         Peripheral Channel Register? (PCR) API is provided to access those
>
> What does the ? mean? We are not sure what PCR stands for?

That's right. I cannot actually find a reference. The abbreviations
for quite a few things seems to be used without a definition.

[..]

> > diff --git a/include/p2sb.h b/include/p2sb.h
> > new file mode 100644
> > index 00000000000..370f127058c
> > --- /dev/null
> > +++ b/include/p2sb.h
> > @@ -0,0 +1,127 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright 2019 Google LLC
> > + * Written by Simon Glass <sjg@chromium.org>
> > + */
> > +
> > +#ifndef __p2sb_h
> > +#define __p2sb_h
> > +
> > +/* Port Id lives in bits 23:16 and register offset lives in 15:0 of address */
> > +#define PCR_PORTID_SHIFT       16
> > +
> > +/**
> > + * struct p2sb_child_platdata - Information about each child of a p2sb device
> > + *
> > + * @pid: Port ID for this child
> > + */
> > +struct p2sb_child_platdata {
> > +       uint pid;
> > +};
> > +
> > +/**
> > + * struct p2sb_uc_priv - information for the uclass about each device
> > + *
> > + * This must be set up by the driver when it is probed
> > + *
> > + * @mmio_base: Base address of P2SB region
> > + */
> > +struct p2sb_uc_priv {
> > +       uint mmio_base;
> > +};
> > +
> > +/**
> > + * struct p2sb_ops - Operations for the P2SB (none at present)
> > + */
> > +struct p2sb_ops {
> > +};
> > +
> > +#define p2sb_get_ops(dev)        ((struct p2sb_ops *)(dev)->driver->ops)
> > +
> > +/**
> > + * pcr_read32/16/8() - Read from a PCR device
> > + *
> > + * Reads data from a PCR device within the P2SB
> > + *
> > + * @dev: Device to read from
> > + * @offset: Offset within device to read
> > + * @return value read
> > + */
> > +uint pcr_read32(struct udevice *dev, uint offset);
> > +uint pcr_read16(struct udevice *dev, uint offset);
> > +uint pcr_read8(struct udevice *dev, uint offset);
> > +
> > +/**
> > + * pcr_read32/16/8() - Write to a PCR device
> > + *
> > + * Writes data to a PCR device within the P2SB
>
> Read data
>
> > + *
> > + * @dev: Device to write to
> > + * @offset: Offset within device to write
> > + * @data: Data to write
> > + */
> > +void pcr_write32(struct udevice *dev, uint offset, uint data);
> > +void pcr_write16(struct udevice *dev, uint offset, uint data);
> > +void pcr_write8(struct udevice *dev, uint offset, uint data);
> > +
> > +/**
> > + * pcr_clrsetbits32/16/8() - Update a PCR device
> > + *
> > + * Updates dat in a PCR device within the P2SB
> > + *
> > + * This reads from the device, clears and set bits, then writes back.
> > + *
> > + * new_data = (old_data & ~clr) | set
> > + *
> > + * @dev: Device to update
> > + * @offset: Offset within device to update
> > + * @clr: Bits to clear after reading
> > + * @set: Bits to set before writing
> > + */
> > +void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set);
> > +void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set);
> > +void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set);
> > +
> > +static inline void pcr_setbits32(struct udevice *dev, uint offset, uint set)
> > +{
> > +       return pcr_clrsetbits32(dev, offset, 0, set);
> > +}
> > +
> > +static inline void pcr_setbits16(struct udevice *dev, uint offset, uint set)
> > +{
> > +       return pcr_clrsetbits16(dev, offset, 0, set);
> > +}
> > +
> > +static inline void pcr_setbits8(struct udevice *dev, uint offset, uint set)
> > +{
> > +       return pcr_clrsetbits8(dev, offset, 0, set);
> > +}
> > +
> > +static inline void pcr_clrbits32(struct udevice *dev, uint offset, uint clr)
> > +{
> > +       return pcr_clrsetbits32(dev, offset, clr, 0);
> > +}
> > +
> > +static inline void pcr_clrbits16(struct udevice *dev, uint offset, uint clr)
> > +{
> > +       return pcr_clrsetbits16(dev, offset, clr, 0);
> > +}
> > +
> > +static inline void pcr_clrbits8(struct udevice *dev, uint offset, uint clr)
> > +{
> > +       return pcr_clrsetbits8(dev, offset, clr, 0);
> > +}
> > +
> > +/**
> > + * p2sb_set_port_id() - Set the port ID for a p2sb child device
> > + *
> > + * This must be called in a device's bind() method when OF_PLATDATA is used
> > + * since the uclass cannot access the device's of-platdata.
> > + *
> > + * @dev: Child device (whose parent is UCLASS_P2SB)
> > + * @portid: Port ID of child device
> > + * @return 0 if OK, -ENODEV is the p2sb device could not be found
> > + */
> > +int p2sb_set_port_id(struct udevice *dev, int portid);
> > +
> > +#endif
> > --
>
> I still are not sure P2SB is generic enough to merit a uclass driver.

If you look at the device tree it works really well. It is a bit
similar to a simple-bus but has its own functionality, such as
children accessing their memory-mapped regions under control of the
uclass. In that it is similar to i2c or PCI, which have uclasses. We
have child nodes of the p2sb, and in the case of pinctrl they have
grandchild nodes (in my latest update, not v3).

It is true that this is specific to x86, but I don't see a problem
with that. We have other uclasses that are arch-specific.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support
  2019-11-19  7:25   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi BIn,

On Tue, 19 Nov 2019 at 00:25, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Add support for some important configuration options and FSP memory init.
> > The memory init uses swizzle tables from the device tree.
> >
> > Support for the FSP_S binary is also included.
> >
> > Bootstage timing is used for both FSP_M and FSP_M and memory-mapped SPI
>
> FSP_T and FSP_M ?

Will fix

>
> > reads.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > - Add a proper implementation of fsp_notify
> > - Add an fsp: tag
> > - Add bootstage timing for memory-mapped reads
> > - Add fsp_locate_fsp to locate an fsp component
> > - Add fspm_done() hook
> > - Add support for FSP-S component and VBT
> > - Simplify types for fsp_locate_fsp()
> > - Switch mmap to use SPI instead of SPI flash
> >
> > Changes in v2: None
> >
> >  arch/x86/Kconfig                         |  61 ++++++++-
> >  arch/x86/include/asm/fsp2/fsp_api.h      |  60 +++++++++
> >  arch/x86/include/asm/fsp2/fsp_internal.h |  97 ++++++++++++++
> >  arch/x86/lib/fsp2/Makefile               |  10 ++
> >  arch/x86/lib/fsp2/fsp_common.c           |  13 ++
> >  arch/x86/lib/fsp2/fsp_dram.c             |  77 +++++++++++
> >  arch/x86/lib/fsp2/fsp_init.c             | 157 +++++++++++++++++++++++
> >  arch/x86/lib/fsp2/fsp_meminit.c          |  97 ++++++++++++++
> >  arch/x86/lib/fsp2/fsp_silicon_init.c     |  52 ++++++++
> >  arch/x86/lib/fsp2/fsp_support.c          | 129 +++++++++++++++++++
> >  include/bootstage.h                      |   3 +
> >  11 files changed, 754 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/x86/include/asm/fsp2/fsp_api.h
> >  create mode 100644 arch/x86/include/asm/fsp2/fsp_internal.h
> >  create mode 100644 arch/x86/lib/fsp2/Makefile
> >  create mode 100644 arch/x86/lib/fsp2/fsp_common.c
> >  create mode 100644 arch/x86/lib/fsp2/fsp_dram.c
> >  create mode 100644 arch/x86/lib/fsp2/fsp_init.c
> >  create mode 100644 arch/x86/lib/fsp2/fsp_meminit.c
> >  create mode 100644 arch/x86/lib/fsp2/fsp_silicon_init.c
> >  create mode 100644 arch/x86/lib/fsp2/fsp_support.c
> >
> > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> > index 17a6fe6d3d9..cbd3fc4f581 100644
> > --- a/arch/x86/Kconfig
> > +++ b/arch/x86/Kconfig
> > @@ -326,7 +326,7 @@ config X86_RAMTEST
> >
> >  config FLASH_DESCRIPTOR_FILE
> >         string "Flash descriptor binary filename"
> > -       depends on HAVE_INTEL_ME
> > +       depends on HAVE_INTEL_ME || FSP_VERSION2
> >         default "descriptor.bin"
> >         help
> >           The filename of the file to use as flash descriptor in the
> > @@ -411,6 +411,63 @@ config FSP_ADDR
> >           The default base address of 0xfffc0000 indicates that the binary must
> >           be located at offset 0xc0000 from the beginning of a 1MB flash device.
> >
> > +if FSP_VERSION2
> > +
> > +config FSP_FILE_T
> > +       string "Firmware-Support-Package binary filename (Temp RAM)"
> > +       default "fsp_t.bin"
> > +       help
> > +         The filename of the file to use for the temporary-RAM init phase from
> > +         the Firmware-Support-Package binary. Put this in the board directory.
> > +         It is used to set up an initial area of RAM which can be used for the
> > +         stack and other purposes, while bringing up the main system DRAM.
> > +
> > +config FSP_ADDR_T
> > +       hex "Firmware-Support-Package binary location (Temp RAM)"
> > +       default 0xffff8000
> > +       help
> > +         FSP is not Position-Independent Code (PIC) and FSP components have to
> > +         be rebased if placed at a location which is different from the
> > +         perferred base address specified during the FSP build. Use Intel's
> > +         Binary Configuration Tool (BCT) to do the rebase.
> > +
> > +config FSP_FILE_M
> > +       string "Firmware-Support-Package binary filename (Memory Init)"
> > +       default "fsp_m.bin"
> > +       help
> > +         The filename of the file to use for the RAM init phase from the
> > +         Firmware Support Package binary. Put this in the board directory.
> > +         It is used to set up the main system DRAM and runs in SPL, once
> > +         temporary RAM (CAR) is working.
> > +
> > +config FSP_FILE_S
> > +       string "Firmware-Support-Package binary filename (Silicon Init)"
> > +       default "fsp_s.bin"
> > +       help
> > +         The filename of the file to use for the Silicon init phase from the
> > +         Firmware Support Package binary. Put this in the board directory.
> > +         It is used to set up the silicon to work correctly and must be
> > +         executed after DRAM is running.
> > +
> > +config FSP_FILE_VBT
>
> There is already a VBT_FILE config option for this.

Oops, will drop.

One issue here is that we are using hard-coded positions for things
that don't need to be in a fixed place (I think). It makes it harder
to avoid image overlays.

Now that we have a way to read symbols from binman, perhaps some of
the addresses should be left out? Then binman can pack them
automatically.

>
> > +       string "Firmware-Support-Package Video BIOS Table (VBT)"
> > +       default "vbt.bin"
> > +       help
> > +         The filename of the file to use for the video data needd by the
> > +         Silicon init phase from the Firmware Support Package binary. Put this
> > +         in the board directory. It is used to set up the video parameters so
> > +         that the display can be used.
> > +
> > +config IFWI_INPUT_FILE
> > +       string "Filename containing FIT (Firmware Interface Table) with IFWI"
> > +       default "fitimage.bin"
> > +       help
> > +         The IFWI is obtained by running a tool on this file to extract the
> > +         IFWI. Put this in the board directory. The IFWI contains U-Boot TPL,
> > +         microcode and other internal items.
> > +
> > +endif
> > +
> >  config FSP_TEMP_RAM_ADDR
> >         hex
> >         depends on FSP_VERSION1
> > @@ -629,7 +686,7 @@ config VBT_ADDR
> >
> >  config VIDEO_FSP
> >         bool "Enable FSP framebuffer driver support"
> > -       depends on HAVE_VBT && DM_VIDEO
> > +       depends on (HAVE_VBT || FSP_VERSION2) && DM_VIDEO
> >         help
> >           Turn on this option to enable a framebuffer driver when U-Boot is
> >           using Video BIOS Table (VBT) image for FSP firmware to initialize
> > diff --git a/arch/x86/include/asm/fsp2/fsp_api.h b/arch/x86/include/asm/fsp2/fsp_api.h
> > new file mode 100644
> > index 00000000000..93b6472dce0
> > --- /dev/null
> > +++ b/arch/x86/include/asm/fsp2/fsp_api.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: Intel */
> > +/*
> > + * Copyright (C) 2015-2016 Intel Corp.
> > + * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
> > + * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
> > + * Mostly taken from coreboot fsp2_0/memory_init.c
> > + */
> > +
> > +#ifndef __ASM_FSP2_API_H
> > +#define __ASM_FSP2_API_H
> > +
> > +#include <asm/fsp/fsp_api.h>
> > +
> > +struct fspm_upd;
> > +struct fsps_upd;
> > +struct hob_header;
> > +
> > +enum fsp_boot_mode {
> > +       FSP_BOOT_WITH_FULL_CONFIGURATION = 0x00,
> > +       FSP_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01,
> > +       FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02,
> > +       FSP_BOOT_ON_S4_RESUME = 0x05,
> > +       FSP_BOOT_ON_S3_RESUME = 0x11,
> > +       FSP_BOOT_ON_FLASH_UPDATE = 0x12,
> > +       FSP_BOOT_IN_RECOVERY_MODE = 0x20
> > +};
> > +
> > +struct __packed fsp_upd_header {
> > +       u64     signature;
> > +       u8      revision;
> > +       u8      reserved[23];
> > +};
> > +
> > +/**
> > + * fsp_memory_init() - Init the SDRAM
> > + *
> > + * @s3wake: true if we are booting from resume, so cannot reinit the mememory
> > + *     from scatch since we will lose its contents
> > + * @use_spi_flash: true to use the fast SPI driver to read FSP, otherwise use
> > + *     mapped SPI
> > + * @return 0 if OK, -ve on error
> > + */
> > +int fsp_memory_init(bool s3wake, bool use_spi_flash);
> > +
> > +typedef asmlinkage int (*fsp_memory_init_func)(struct fspm_upd *params,
> > +                                              struct hob_header **hobp);
> > +
> > +/**
> > + * fsp_silicon_init() - Init the silicon
> > + *
> > + * This calls the FSP's 'silicon init' entry point
> > + *
> > + * @s3wake: true if we are booting from resume
>
> Should have the same descriptions as fsp_memory_init()
>
> > + * @return 0 if OK, -ve on error
> > + */
> > +int fsp_silicon_init(bool s3wake, bool use_spi_flash);
> > +
> > +typedef asmlinkage int (*fsp_silicon_init_func)(struct fsps_upd *params);
> > +
> > +#endif
> > diff --git a/arch/x86/include/asm/fsp2/fsp_internal.h b/arch/x86/include/asm/fsp2/fsp_internal.h
> > new file mode 100644
> > index 00000000000..5893f1ffcc7
> > --- /dev/null
> > +++ b/arch/x86/include/asm/fsp2/fsp_internal.h
> > @@ -0,0 +1,97 @@
> > +/* SPDX-License-Identifier: Intel */
> > +/*
> > + * Copyright (C) 2015-2016 Intel Corp.
> > + * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
> > + * Mostly taken from coreboot
> > + */
> > +
> > +#ifndef __ASM_FSP_INTERNAL_H
> > +#define __ASM_FSP_INTERNAL_H
> > +
> > +struct binman_entry;
> > +struct fsp_header;
> > +struct fspm_upd;
> > +struct fsps_upd;
> > +
> > +enum fsp_type_t {
> > +       FSP_M,
> > +       FSP_S,
> > +};
> > +
> > +int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
> > +                  struct fsp_header **fspp);
> > +
> > +/**
> > + * fsp_locate_fsp() - Locate an FSP component
> > + *
> > + * This finds an FSP component by various methods. It is not as general-purpose
> > + * as it looks, since it expects FSP-M to be requested in SPL (only), and FSP-S
> > + * to be requested in U-Boot proper.
> > + *
> > + * @type: Component to locate
> > + * @entry: Returns location of component
> > + * @use_spi_flash: true to read using the Fast SPI driver, false to use
> > + *     memory-mapped SPI flash
> > + * @devp: Returns northbridge device
> > + * @hdrp: Returns FSP header
> > + * @rom_offsetp: If non-NULL, returns the offset to add to any image position to
> > + *     find the memory-mapped location of that position. For example, for ROM
> > + *     position 0x1000, it will be mapped into 0x1000 + *rom_offsetp.
> > + */
> > +int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
> > +                  bool use_spi_flash, struct udevice **devp,
> > +                  struct fsp_header **hdrp, ulong *rom_offsetp);
> > +
> > +/**
> > + * arch_fsp_s_preinit() - Perform init needed before calling FSP-S
>
> Considering other routines in this file are having fspm_ as the
> prefix, should we name this function to arch_fsps_preinit()?

Will do.

>
> Or rename others to fsp_m_ as the prefix?
>
> > + *
> > + * This allows use of probed drivers and PCI so is a convenient place to do any
> > + * init that is needed before FSP-S is called. After this, U-Boot relocates and
> > + * calls arch_fsp_init_r() before PCI is probed, and that function is not
> > + * allowed to probe PCI before calling FSP-S.
> > + */
> > +int arch_fsp_s_preinit(void);
> > +
> > +/**
> > + * fspm_update_config() - Set up the config structure for FSP-M
> > + *
> > + * @dev: Hostbridge device containing config
> > + * @upd: Config data to fill in
> > + * @return 0 if OK, -ve on error
> > + */
> > +int fspm_update_config(struct udevice *dev, struct fspm_upd *upd);
> > +
> > +/**
> > + * fspm_done() - Indicate that memory init is complete
> > + *
> > + * This allows the board to do whatever post-init it needs before things
> > + * continue.
> > + *
> > + * @dev: Hostbridge device
> > + * @return 0 if OK, -ve on error
> > + */
> > +int fspm_done(struct udevice *dev);
> > +
> > +/**
> > + * fsps_update_config() - Set up the config structure for FSP-S
> > + *
> > + * @dev: Hostbridge device containing config
> > + * @rom_offset: Value to add to convert from ROM offset to memory-mapped address
> > + * @upd: Config data to fill in
> > + * @return 0 if OK, -ve on error
> > + */
> > +int fsps_update_config(struct udevice *dev, ulong rom_offset,
> > +                      struct fsps_upd *upd);
> > +
> > +/**
> > + * prepare_mrc_cache() - Read the MRC cache into the product-data struct
> > + *
> > + * This looks for cached Memory-reference code (MRC) data and stores it into
> > + * @upd for use by the FSP-M binary.
> > + *
> > + * @return 0 if OK, -ENOENT if no data (whereupon the caller can continue and
> > + *     expect a slower boot), other -ve value on other error
> > + */
> > +int prepare_mrc_cache(struct fspm_upd *upd);
> > +
> > +#endif
> > diff --git a/arch/x86/lib/fsp2/Makefile b/arch/x86/lib/fsp2/Makefile
> > new file mode 100644
> > index 00000000000..ddbe2d0db26
> > --- /dev/null
> > +++ b/arch/x86/lib/fsp2/Makefile
> > @@ -0,0 +1,10 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# Copyright 2019 Google LLC
> > +
> > +obj-y += fsp_common.o
> > +obj-y += fsp_dram.o
> > +obj-y += fsp_init.o
> > +obj-y += fsp_meminit.o
> > +obj-y += fsp_silicon_init.o
> > +obj-y += fsp_support.o
> > diff --git a/arch/x86/lib/fsp2/fsp_common.c b/arch/x86/lib/fsp2/fsp_common.c
> > new file mode 100644
> > index 00000000000..f69456e43a2
> > --- /dev/null
> > +++ b/arch/x86/lib/fsp2/fsp_common.c
> > @@ -0,0 +1,13 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2019 Google LLC
> > + * Written by Simon Glass <sjg@chromium.org>
> > + */
> > +
> > +#include <common.h>
> > +#include <init.h>
> > +
> > +int arch_fsp_init(void)
> > +{
> > +       return 0;
> > +}
> > diff --git a/arch/x86/lib/fsp2/fsp_dram.c b/arch/x86/lib/fsp2/fsp_dram.c
> > new file mode 100644
> > index 00000000000..a3f95d0cf96
> > --- /dev/null
> > +++ b/arch/x86/lib/fsp2/fsp_dram.c
> > @@ -0,0 +1,77 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2019 Google LLC
> > + * Written by Simon Glass <sjg@chromium.org>
> > + */
> > +
> > +#include <common.h>
> > +#include <acpi_s3.h>
> > +#include <handoff.h>
> > +#include <spl.h>
> > +#include <asm/arch/cpu.h>
> > +#include <asm/fsp/fsp_support.h>
> > +#include <asm/fsp2/fsp_api.h>
> > +#include <asm/fsp2/fsp_internal.h>
> > +
> > +int dram_init(void)
> > +{
> > +       int ret;
> > +
> > +       if (spl_phase() == PHASE_SPL) {
> > +#ifdef CONFIG_HAVE_ACPI_RESUME
> > +               bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
> > +#else
> > +               bool s3wake = false;
> > +#endif
> > +
> > +               ret = fsp_memory_init(s3wake, BOOT_FROM_FAST_SPI_FLASH);
> > +               if (ret) {
> > +                       debug("Memory init failed (err=%x)\n", ret);
> > +                       return ret;
> > +               }
> > +
> > +               /* The FSP has already set up DRAM, so grab the info we need */
> > +               ret = fsp_scan_for_ram_size();
> > +               if (ret)
> > +                       return ret;
> > +
> > +#ifdef CONFIG_ENABLE_MRC_CACHE
> > +               gd->arch.mrc[MRC_TYPE_NORMAL].buf =
> > +                       fsp_get_nvs_data(gd->arch.hob_list,
> > +                                        &gd->arch.mrc[MRC_TYPE_NORMAL].len);
> > +               gd->arch.mrc[MRC_TYPE_VAR].buf =
> > +                       fsp_get_var_nvs_data(gd->arch.hob_list,
> > +                                            &gd->arch.mrc[MRC_TYPE_VAR].len);
> > +               log_debug("normal %x, var %x\n",
> > +                         gd->arch.mrc[MRC_TYPE_NORMAL].len,
> > +                         gd->arch.mrc[MRC_TYPE_VAR].len);
> > +#endif
> > +       } else {
> > +#if CONFIG_IS_ENABLED(HANDOFF)
> > +               struct spl_handoff *ho = gd->spl_handoff;
> > +
> > +               if (!ho) {
> > +                       debug("No SPL handoff found\n");
> > +                       return -ESTRPIPE;
> > +               }
> > +               gd->ram_size = ho->ram_size;
> > +               handoff_load_dram_banks(ho);
> > +#endif
> > +               ret = arch_fsp_s_preinit();
> > +               if (ret)
> > +                       return log_msg_ret("fsp_s_preinit", ret);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +ulong board_get_usable_ram_top(ulong total_size)
> > +{
> > +#if CONFIG_IS_ENABLED(HANDOFF)
> > +       struct spl_handoff *ho = gd->spl_handoff;
> > +
> > +       return ho->arch.usable_ram_top;
> > +#endif
> > +
> > +       return gd->ram_top;
> > +}
> > diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c
> > new file mode 100644
> > index 00000000000..111eb51d34b
> > --- /dev/null
> > +++ b/arch/x86/lib/fsp2/fsp_init.c
> > @@ -0,0 +1,157 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright 2019 Google LLC
> > + */
> > +
> > +#include <common.h>
> > +#include <binman.h>
> > +#include <binman_sym.h>
> > +#include <cbfs.h>
> > +#include <dm.h>
> > +#include <init.h>
> > +#include <spi.h>
> > +#include <spl.h>
> > +#include <spi_flash.h>
> > +#include <asm/arch/gpio.h>
> > +#include <dm/uclass-internal.h>
> > +#include <asm/fsp2/fsp_internal.h>
> > +
> > +int arch_cpu_init_dm(void)
> > +{
> > +       struct udevice *dev;
> > +       ofnode node;
> > +       int ret;
> > +
> > +       if (spl_phase() != PHASE_BOARD_F)
> > +               return 0;
> > +
> > +       /* Probe all GPIO devices to set up the pads */
> > +       ret = uclass_first_device_err(UCLASS_GPIO, &dev);
>
> Why is this GPIO probe needed in the generic FSP support?

This is for pinctrl, to set up the pads. With v4 I am converting this
to use pinctrl so it should be a little bit clearer. We need to set up
the pins early on, before calling FSP-S.

I think every board will need to do this, so I think it makes sense to
use generate code. What do you think?

>
>
> > +       if (ret)
> > +               return log_msg_ret("no fsp GPIO", ret);
> > +       node = ofnode_path("fsp");
> > +       if (!ofnode_valid(node))
> > +               return log_msg_ret("no fsp params", -EINVAL);
> > +       ret = hostbridge_config_pads_for_node(dev, node);
> > +       if (ret)
> > +               return log_msg_ret("pad config", ret);
> > +
> > +       return ret;
> > +}
> > +
> > +#if !defined(CONFIG_TPL_BUILD)
> > +binman_sym_declare(ulong, intel_fsp_m, image_pos);
> > +binman_sym_declare(ulong, intel_fsp_m, size);
> > +
> > +static int get_coreboot_fsp(enum fsp_type_t type, ulong map_base,
>
> get_uboot_fsp?

Should be cbfs I'll add a comment as this is mostly for development.
>
> > +                           struct binman_entry *entry)
> > +{
> > +       /* Hard-coded position of CBFS in ROM */
>
> Why hard-coded?

Just because this is for development and it doesn't seem worth adding
code to read the FMAP. Will add a comment.

>
> > +       ulong cbfs_base = 0x205000;
> > +       ulong cbfs_size = 0x1bb000;
> > +       struct cbfs_priv *cbfs;
> > +       int ret;
> > +
> > +       ret = cbfs_init_mem(map_base + cbfs_base, cbfs_size, &cbfs);
> > +       if (ret)
> > +               return ret;
> > +       if (!ret) {
> > +               const struct cbfs_cachenode *node;
> > +
> > +               node = cbfs_find_file(cbfs, "fspm.bin");
> > +               if (!node)
> > +                       return log_msg_ret("fspm node", -ENOENT);
> > +
> > +               entry->image_pos = (ulong)node->data;
> > +               entry->size = node->data_length;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
> > +                  bool use_spi_flash, struct udevice **devp,
> > +                  struct fsp_header **hdrp, ulong *rom_offsetp)
> > +{
> > +       ulong mask = CONFIG_ROM_SIZE - 1;
> > +       struct udevice *dev;
> > +       ulong rom_offset = 0;
> > +       uint map_size;
> > +       ulong map_base;
> > +       uint offset;
> > +       int ret;
> > +
> > +       /*
> > +        * Find the devices but don't probe them, since we don't want to
> > +        * auto-config PCI before silicon init runs
> > +        */
> > +       ret = uclass_find_first_device(UCLASS_NORTHBRIDGE, &dev);
> > +       if (ret)
> > +               return log_msg_ret("Cannot get northbridge", ret);
> > +       if (!use_spi_flash) {
> > +               struct udevice *sf;
> > +
> > +               /* Just use the SPI driver to get the memory map */
> > +               ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf);
> > +               if (ret)
> > +                       return log_msg_ret("Cannot get SPI flash", ret);
> > +               ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset);
> > +               if (ret)
> > +                       return log_msg_ret("Could not get flash mmap", ret);
> > +       }
> > +
> > +       if (spl_phase() >= PHASE_BOARD_F) {
> > +               if (type != FSP_S)
> > +                       return -EPROTONOSUPPORT;
> > +               ret = binman_entry_find("intel-fsp-s", entry);
> > +               if (ret)
> > +                       return log_msg_ret("binman entry", ret);
> > +               if (!use_spi_flash)
> > +                       rom_offset = (map_base & mask) - CONFIG_ROM_SIZE;
> > +       } else {
> > +               ret = -ENOENT;
> > +               if (false)
> > +                       /* Support using a hybrid image build by coreboot */
>
> U-Boot?

No it is actually coreboot.  It lets coreboot do the early stages so
we can make sure U-Boot is doing the same things it should. See above.

[..]

> > +int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
> > +                  struct fsp_header **fspp)
> > +{
> > +       static efi_guid_t guid = FSP_HEADER_GUID;
> > +       struct fv_ext_header *exhdr;
> > +       struct fsp_header *fsp;
> > +       struct ffs_file_header *file_hdr;
> > +       struct fv_header *fv;
> > +       struct raw_section *raw;
> > +       void *ptr, *base;
> > +       u8 buf[PROBE_BUF_SIZE];
> > +       struct udevice *dev;
> > +       int ret;
> > +
> > +       /* You are in a maze of twisty headers all alike */
>
> What does this comment mean?

Web search it :-)

I'll expand the comment.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot
  2019-11-19  8:34   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, 19 Nov 2019 at 01:34, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > The existing work-around for positioning U-Boot in the ROM when it
> > actually runs from RAM still exists and there is not obvious way to change
> > this.
> >
> > Add a proper Kconfig option to handle this case. This also adds a new bool
> > property to indicate whether CONFIG_SYS_TEXT_BASE exists.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  Kconfig                                |  9 ++++++---
> >  arch/x86/Kconfig                       |  5 +++++
> >  arch/x86/dts/u-boot.dtsi               | 18 +++---------------
> >  configs/chromebook_samus_tpl_defconfig |  1 +
> >  4 files changed, 15 insertions(+), 18 deletions(-)
> >

[..]

> > diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig
> > index 28f23cfe125..c7f125eaa40 100644
> > --- a/configs/chromebook_samus_tpl_defconfig
> > +++ b/configs/chromebook_samus_tpl_defconfig
> > @@ -13,6 +13,7 @@ CONFIG_HAVE_REFCODE=y
> >  CONFIG_SMP=y
> >  CONFIG_HAVE_VGA_BIOS=y
> >  CONFIG_SPL_TEXT_BASE=0xffe70000
> > +CONFIG_X86_OFFSET_U_BOOT=0xfff00000
>
> Should we update other x86 board defconfig files for this option?

It defaults to the same as the text base, which works fine with XIP,
so I don't think this is necessary.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size()
  2019-11-19 14:36   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  2019-11-21 14:04       ` Bin Meng
  0 siblings, 1 reply; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, 19 Nov 2019 at 07:36, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > This incorrectly shortens read operations if there is a maximum write size
> > but no maximum read size. Fix it.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  drivers/spi/ich.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > index 7f73f096ecb..b28f3423584 100644
> > --- a/drivers/spi/ich.c
> > +++ b/drivers/spi/ich.c
> > @@ -424,9 +424,11 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
> >                 page_offset = do_div(aux, ICH_BOUNDARY);
> >         }
> >
> > -       if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
> > -               op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> > -                                     slave->max_read_size);
> > +       if (op->data.dir == SPI_MEM_DATA_IN) {
> > +               if (slave->max_read_size) {
> > +                       op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> > +                                             slave->max_read_size);
> > +               }
>
> Isn't the changed one the same as the old codes?

The old code fails if max_read_size is 0 but max_write_size is set. It
forgets to take account of max_write_size in that case.


>
> >         } else if (slave->max_write_size) {
> >                 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> >                                       slave->max_write_size);
> > --

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi
  2019-11-20 12:48       ` Bin Meng
@ 2019-11-21 13:50         ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Wed, 20 Nov 2019 at 05:48, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Wed, Nov 20, 2019 at 1:53 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Bin,
> >
> > On Tue, 19 Nov 2019 at 06:36, Bin Meng <bmeng.cn@gmail.com> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > The Intel Fast SPI interface is similar to ICH. Add of-platdata support
> > > > for this using the "intel,fast-spi" compatible string.
> > > >
> > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > ---
> > > >
> > > > Changes in v3: None
> > > > Changes in v2: None
> > > >
> > > >  drivers/spi/ich.c | 17 ++++++++++++++---
> > > >  1 file changed, 14 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > > > index b28f3423584..ae3bff36bba 100644
> > > > --- a/drivers/spi/ich.c
> > > > +++ b/drivers/spi/ich.c
> > > > @@ -10,6 +10,7 @@
> > > >  #include <common.h>
> > > >  #include <div64.h>
> > > >  #include <dm.h>
> > > > +#include <dt-structs.h>
> > > >  #include <errno.h>
> > > >  #include <malloc.h>
> > > >  #include <pch.h>
> > > > @@ -28,9 +29,13 @@
> > > >  #endif
> > > >
> > > >  struct ich_spi_platdata {
> > > > +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> > > > +       struct dtd_intel_fast_spi dtplat;
> > > > +#endif
> > > >         enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > > >         bool lockdown;                  /* lock down controller settings? */
> > > >         ulong mmio_base;                /* Base of MMIO registers */
> > > > +       pci_dev_t bdf;                  /* PCI address used by of-platdata */
> > > >  };
> > > >
> > > >  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> > > > @@ -597,10 +602,16 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
> > > >  {
> > > >         struct ich_spi_platdata *plat = dev_get_platdata(dev);
> > > >
> > > > +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> > > >         plat->ich_version = dev_get_driver_data(dev);
> > > >         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> > > > -
> > > >         pch_get_spi_base(dev->parent, &plat->mmio_base);
> > > > +#else
> > > > +       plat->ich_version = ICHV_APL;
> > >
> > > I don't think the ICH_VERSION is something that is controlled via OF_PLATDATA.
> >
> > Well, the fact that we are using dtd_intel_fast_spi means that the
> > compatible string is intel,fast-spi, so that's why we set this version
> > variable. The older SPI-controller versions don't actually support
> > of-platdata, so this is safe.
> >
>
> What if we have another platform that uses OF_PLATDATA but is not
> ICHV_APL? How do we distinguish that?
>
> > >
> > > > +       plat->mmio_base = plat->dtplat.early_regs[0];
> > > > +       plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> > > > +#endif
> > > > +       debug("%s: mmio_base=%lx\n", __func__, plat->mmio_base);
> > > >
> > > >         return 0;
> > > >  }
> > > > @@ -628,8 +639,8 @@ static const struct udevice_id ich_spi_ids[] = {
> > > >         { }
> > > >  };
> > > >
> > > > -U_BOOT_DRIVER(ich_spi) = {
> > > > -       .name   = "ich_spi",
> > > > +U_BOOT_DRIVER(intel_fast_spi) = {
> > >
> > > Why changing the driver name?
> >
> > So that of-platdata will create a U_BOOT_DEVICE() for it and it will
> > be bound. Otherwise the name will not match and the device is ignored.
> >
>
> Could we avoid renaming the driver, ie: reusing the same "ich_spi" name?

Yes, but that would mean we'd have to use a compatible string of
"ich-spi' which breaks the rule of using 'vendor,device'.


>
> > I will update the commit message.
> >
> > >
> > > > +       .name   = "intel_fast_spi",
> > > >         .id     = UCLASS_SPI,
> > > >         .of_match = ich_spi_ids,
> > > >         .ops    = &ich_spi_ops,
> > > > --

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default
  2019-11-20  5:22     ` Vignesh Raghavendra
@ 2019-11-21 13:50       ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Vignesh,

On Tue, 19 Nov 2019 at 22:21, Vignesh Raghavendra <vigneshr@ti.com> wrote:
>
> Hi,
>
> On 19/11/19 7:03 PM, Bin Meng wrote:
> > +Vignesh
> >
> > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >>
> >> We don't normally need this on x86 unless the size of SPI flash devices is
> >> larger than 16MB. This can be enabled by particular SoCs as needed, since
> >> it adds to code size.
> >>
> >> Drop the default enabling of this option on x86.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >>
> >> Changes in v3: None
> >> Changes in v2: None
> >>
> >>  drivers/spi/Kconfig | 1 -
> >>  1 file changed, 1 deletion(-)
> >>
> >> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> >> index b8ca2bdedd5..320baeeb3eb 100644
> >> --- a/drivers/spi/Kconfig
> >> +++ b/drivers/spi/Kconfig
> >> @@ -125,7 +125,6 @@ config FSL_DSPI
> >>
> >>  config ICH_SPI
> >>         bool "Intel ICH SPI driver"
> >> -       imply SPI_FLASH_BAR
> >
> > This was added via:
> >
> > commit 6d82517836418f984b7b4c05cf1427d7b49b1169
> > Author: Vignesh R <vigneshr@ti.com>
> > Date:   Tue Feb 5 11:29:28 2019 +0530
> >
> >     configs: Don't use SPI_FLASH_BAR as default
> >
> >     Now that new SPI NOR layer uses stateless 4 byte opcodes by default,
> >     don't enable SPI_FLASH_BAR. For SPI controllers that cannot support
> >     4-byte addressing, (stm32_qspi.c, fsl_qspi.c, mtk_qspi.c, ich.c,
> >     renesas_rpc_spi.c) add an imply clause to enable SPI_FLASH_BAR so as to
> >     not break functionality.
> >
> > The commit message says: SPI_FLASH_BAR was added so as to not break
> > functionality.
> >
>
> At the time of introducing new SPI NOR layer, I found that (by code
> inspection) ich.c did  not support 4 byte addressing. Hence, "imply
> SPI_FLASH_BAR" was added for ich.c driver.
> But if driver has been improved to support 4 byte addressing or if there
> is no plan to support flashes > 16MiB by default, then it should be okay
> to remove SPI_FLASH_BAR.

Well the problem is that it adds almost 3KB to the code size in TPL,
so I think we need the option to turn it off.

Also current platforms supported in U-Boot don't have more than 8 or
16MB of SPI flash, so this should be safe.

>
> > I don't have board to test right now. Vignesh could you please have a
> > review? Thanks!
> >
> >>         help
> >>           Enable the Intel ICH SPI driver. This driver can be used to
> >>           access the SPI NOR flash on platforms embedding this Intel
> >> --

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata
  2019-11-20 12:52       ` Bin Meng
@ 2019-11-21 13:50         ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Wed, 20 Nov 2019 at 05:52, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Wed, Nov 20, 2019 at 1:53 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Bin,
> >
> > On Tue, 19 Nov 2019 at 06:36, Bin Meng <bmeng.cn@gmail.com> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > It is useful to store the mmio base in platdata. It reduces the amount of
> > > > casting needed. Update the code and move the struct to the C file at the
> > > > same time, as we will need to use with of-platdata.
> > > >
> > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > ---
> > > >
> > > > Changes in v3: None
> > > > Changes in v2: None
> > > >
> > > >  drivers/spi/ich.c | 27 +++++++++++++--------------
> > > >  drivers/spi/ich.h |  5 -----
> > > >  2 files changed, 13 insertions(+), 19 deletions(-)
> > > >
> > > > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > > > index e2bc77bbd58..7f73f096ecb 100644
> > > > --- a/drivers/spi/ich.c
> > > > +++ b/drivers/spi/ich.c
> > > > @@ -27,6 +27,12 @@
> > > >  #define debug_trace(x, args...)
> > > >  #endif
> > > >
> > > > +struct ich_spi_platdata {
> > > > +       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > > > +       bool lockdown;                  /* lock down controller settings? */
> > > > +       ulong mmio_base;                /* Base of MMIO registers */
> > > > +};
> > > > +
> > > >  static u8 ich_readb(struct ich_spi_priv *priv, int reg)
> > > >  {
> > > >         u8 value = readb(priv->base + reg);
> > > > @@ -466,16 +472,9 @@ static int ich_init_controller(struct udevice *dev,
> > > >                                struct ich_spi_platdata *plat,
> > > >                                struct ich_spi_priv *ctlr)
> > > >  {
> > > > -       ulong sbase_addr;
> > > > -       void *sbase;
> > > > -
> > > > -       /* SBASE is similar */
> > > > -       pch_get_spi_base(dev->parent, &sbase_addr);
> > > > -       sbase = (void *)sbase_addr;
> > > > -       debug("%s: sbase=%p\n", __func__, sbase);
> > > > -
> > > > +       ctlr->base = (void *)plat->mmio_base;
> > > >         if (plat->ich_version == ICHV_7) {
> > > > -               struct ich7_spi_regs *ich7_spi = sbase;
> > > > +               struct ich7_spi_regs *ich7_spi = ctlr->base;
> > > >
> > > >                 ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
> > > >                 ctlr->menubytes = sizeof(ich7_spi->opmenu);
> > > > @@ -487,9 +486,8 @@ static int ich_init_controller(struct udevice *dev,
> > > >                 ctlr->control = offsetof(struct ich7_spi_regs, spic);
> > > >                 ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
> > > >                 ctlr->preop = offsetof(struct ich7_spi_regs, preop);
> > > > -               ctlr->base = ich7_spi;
> > > >         } else if (plat->ich_version == ICHV_9) {
> > > > -               struct ich9_spi_regs *ich9_spi = sbase;
> > > > +               struct ich9_spi_regs *ich9_spi = ctlr->base;
> > > >
> > > >                 ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
> > > >                 ctlr->menubytes = sizeof(ich9_spi->opmenu);
> > > > @@ -504,7 +502,6 @@ static int ich_init_controller(struct udevice *dev,
> > > >                 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
> > > >                 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
> > > >                 ctlr->pr = &ich9_spi->pr[0];
> > > > -               ctlr->base = ich9_spi;
> > > >         } else {
> > > >                 debug("ICH SPI: Unrecognised ICH version %d\n",
> > > >                       plat->ich_version);
> > > > @@ -515,8 +512,8 @@ static int ich_init_controller(struct udevice *dev,
> > > >         ctlr->max_speed = 20000000;
> > > >         if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
> > > >                 ctlr->max_speed = 33000000;
> > > > -       debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
> > > > -             plat->ich_version, ctlr->base, ctlr->max_speed);
> > > > +       debug("ICH SPI: Version ID %d detected at %lx, speed %ld\n",
> > > > +             plat->ich_version, plat->mmio_base, ctlr->max_speed);
> > > >
> > > >         ich_set_bbar(ctlr, 0);
> > > >
> > > > @@ -601,6 +598,8 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev)
> > > >         plat->ich_version = dev_get_driver_data(dev);
> > > >         plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
> > > >
> > > > +       pch_get_spi_base(dev->parent, &plat->mmio_base);
> > >
> > > In patch [77], spi: ich: Move the protection/lockdown code into a
> > > function, we already removed the assumption of dev->parent, but used
> > > priv->pch for the PCH device.
> >
> > Yes, this should use priv->pch, I think.
> >
> > >
> > > > +
> > > >         return 0;
> > > >  }
> > > >
> > > > diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
> > > > index 77057878a5d..623b2c547a6 100644
> > > > --- a/drivers/spi/ich.h
> > > > +++ b/drivers/spi/ich.h
> > > > @@ -168,11 +168,6 @@ enum ich_version {
> > > >         ICHV_9,
> > > >  };
> > > >
> > > > -struct ich_spi_platdata {
> > > > -       enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > > > -       bool lockdown;                  /* lock down controller settings? */
> > > > -};
> > >
> > > I don't understand why moving this struct to C file?
> >
> > We need to add of-platdata to this struct and don't want to do that in
> > a header file. It  ends up begin:
> >
> > struct ich_spi_platdata {
> > #if CONFIG_IS_ENABLED(OF_PLATDATA)
> >    struct dtd... ...;
> > #endif
> >        enum ich_version ich_version;   /* Controller version, 7 or 9 */
> > ...
> > }
> >
> > All structs that use of-platdata should be in C files, I think.
> >
>
> Is this hard requirement for drivers with of-platdata? Maybe we need
> update of-plat.rst to better document this rule.

Will add this in a new patch.

Yes I think using of-platdata.h in a header file would be bad.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method
  2019-11-19 14:36   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi BIn,

On Tue, 19 Nov 2019 at 07:37, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Add this method so that the memory-mapped location of the SPI flash can
> > be queried.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  drivers/spi/ich.c | 32 ++++++++++++++++++++++++++++++++
> >  1 file changed, 32 insertions(+)
> >
> > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > index ae1dc64bde8..ec0f77f6e40 100644
> > --- a/drivers/spi/ich.c
> > +++ b/drivers/spi/ich.c
> > @@ -610,6 +610,37 @@ static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
> >         return ret;
> >  }
> >
> > +static int ich_get_mmap_bus(struct udevice *bus, ulong *map_basep,
> > +                           uint *map_sizep, uint *offsetp)
> > +{
> > +       pci_dev_t spi_bdf;
> > +
> > +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> > +       struct pci_child_platdata *pplat = dev_get_parent_platdata(bus);
> > +
> > +       spi_bdf = pplat->devfn;
> > +#else
> > +       struct ich_spi_platdata *plat = dev_get_platdata(bus);
> > +
> > +       /*
> > +        * We cannot rely on plat->bdf being set up yet since this method can
> > +        * be called before the device is probed. Use the of-platdata directly
> > +        * instead.
> > +        */
> > +       spi_bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
> > +#endif
> > +
> > +       return fast_spi_get_bios_mmap(spi_bdf, map_basep, map_sizep, offsetp);
>
> I think we should move fast_spi_get_bios_mmap() to this driver,
> instead of having the ICH driver depend on something external.

The problem is that this function is needed in APL's cpu_spl.c to
cache the BIOS region.and also by rom_load_image() to read from the
mapped SPI flash.

This driver is in fact not normally included in TPL, since it is quite
large and not needed.

So we have to call these functions from outside the driver and
therefore it is best to have them in the arch-specific code.

It is in intel_common so is shared.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support
  2019-11-19 14:52   ` Bin Meng
@ 2019-11-21 13:50     ` Simon Glass
  0 siblings, 0 replies; 201+ messages in thread
From: Simon Glass @ 2019-11-21 13:50 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Tue, 19 Nov 2019 at 07:52, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > In TPL we want to reduce code size and support running with CONFIG_PCI
> > disabled. Add special code to handle this using a fixed BAR programmed
> > into the SPI on boot. Also cache the SPI flash to speed up boot.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  drivers/spi/ich.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
> >  1 file changed, 42 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > index ec0f77f6e40..daa69c25a3a 100644
> > --- a/drivers/spi/ich.c
> > +++ b/drivers/spi/ich.c
> > @@ -19,8 +19,10 @@
> >  #include <spi.h>
> >  #include <spi_flash.h>
> >  #include <spi-mem.h>
> > +#include <spl.h>
> >  #include <asm/fast_spi.h>
> >  #include <asm/io.h>
> > +#include <asm/mtrr.h>
> >
> >  #include "ich.h"
> >
> > @@ -114,6 +116,8 @@ static bool ich9_can_do_33mhz(struct udevice *dev)
> >  {
> >         u32 fdod, speed;
> >
> > +       if (!CONFIG_IS_ENABLED(PCI))
> > +               return false;
> >         /* Observe SPI Descriptor Component Section 0 */
> >         dm_pci_write_config32(dev->parent, 0xb0, 0x1000);
> >
> > @@ -705,6 +709,15 @@ static int ich_init_controller(struct udevice *dev,
> >                                struct ich_spi_platdata *plat,
> >                                struct ich_spi_priv *ctlr)
> >  {
> > +       if (spl_phase() == PHASE_TPL) {
> > +               struct ich_spi_platdata *plat = dev_get_platdata(dev);
> > +               int ret;
> > +
> > +               ret = fast_spi_early_init(plat->bdf, plat->mmio_base);
>
> Can we move the fast_spi_early_init() contents to ich_spi_probe(),
> where the bios_cntl register is programmed to disable the write
> protect for ICH_V7? This helps reading as it's disabling write
> protect, but for different ICH SPI variants.

That driver is not included in TPL. It adds about 7KB to code size and
puts us very close to the limit.

Regards,
Simon

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size()
  2019-11-21 13:50     ` Simon Glass
@ 2019-11-21 14:04       ` Bin Meng
  0 siblings, 0 replies; 201+ messages in thread
From: Bin Meng @ 2019-11-21 14:04 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, Nov 21, 2019 at 9:50 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Tue, 19 Nov 2019 at 07:36, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Mon, Oct 21, 2019 at 11:40 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > This incorrectly shortens read operations if there is a maximum write size
> > > but no maximum read size. Fix it.
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > ---
> > >
> > > Changes in v3: None
> > > Changes in v2: None
> > >
> > >  drivers/spi/ich.c | 8 +++++---
> > >  1 file changed, 5 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> > > index 7f73f096ecb..b28f3423584 100644
> > > --- a/drivers/spi/ich.c
> > > +++ b/drivers/spi/ich.c
> > > @@ -424,9 +424,11 @@ static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
> > >                 page_offset = do_div(aux, ICH_BOUNDARY);
> > >         }
> > >
> > > -       if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
> > > -               op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> > > -                                     slave->max_read_size);
> > > +       if (op->data.dir == SPI_MEM_DATA_IN) {
> > > +               if (slave->max_read_size) {
> > > +                       op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> > > +                                             slave->max_read_size);
> > > +               }
> >
> > Isn't the changed one the same as the old codes?
>
> The old code fails if max_read_size is 0 but max_write_size is set. It
> forgets to take account of max_write_size in that case.
>

I still don't get this. Based on your description, it seems that your
logic works if we remove the } before the else if

>
> >
> > >         } else if (slave->max_write_size) {
> > >                 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
> > >                                       slave->max_write_size);
> > > --
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 201+ messages in thread

end of thread, other threads:[~2019-11-21 14:04 UTC | newest]

Thread overview: 201+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-21  3:37 [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Simon Glass
2019-10-21  3:37 ` [U-Boot] [PATCH v3 023/108] x86: timer: Allow a timer base of 0 Simon Glass
2019-10-28 13:02   ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 024/108] x86: spl: Support init of a PUNIT Simon Glass
2019-10-28  7:12   ` Bin Meng
2019-11-02  9:49     ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 025/108] x86: tpl: Add a fake PCI bus Simon Glass
2019-10-21  7:52   ` Andy Shevchenko
2019-10-21 22:53     ` Simon Glass
2019-10-22  8:19       ` Andy Shevchenko
2019-10-22 13:50         ` Simon Glass
2019-10-28  7:12   ` Bin Meng
2019-11-02  9:49     ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 026/108] x86: timer: Reduce timer code size in TPL on Intel CPUs Simon Glass
2019-10-28  7:26   ` Bin Meng
2019-11-02 18:25     ` Simon Glass
2019-10-21  3:37 ` [U-Boot] [PATCH v3 027/108] x86: Drop unnecessary cpu code for TPL Simon Glass
2019-10-28 12:56   ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 028/108] x86: Drop unnecessary interrupt " Simon Glass
2019-10-28  7:49   ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 029/108] x86: Add a CPU init function " Simon Glass
2019-10-28  7:50   ` Bin Meng
2019-11-02  9:58     ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 030/108] x86: Move CPU init to before spl_init() Simon Glass
2019-10-28  7:52   ` Bin Meng
2019-11-02  9:58     ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 031/108] x86: Don't print CPU info in TPL Simon Glass
2019-11-02  5:52   ` Bin Meng
2019-11-02  9:58     ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 032/108] x86: Quieten TPL's jump_to_image_no_args() Simon Glass
2019-11-02  5:52   ` Bin Meng
2019-11-02  9:58     ` Bin Meng
2019-10-21  3:37 ` [U-Boot] [PATCH v3 033/108] x86: power: Add an ACPI PMC uclass Simon Glass
2019-11-02  5:52   ` Bin Meng
2019-11-04  8:02   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-10-21  3:37 ` [U-Boot] [PATCH v3 034/108] x86: sandbox: Add a PMC emulator and test Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 035/108] x86: power: Add a 'pmc' command Simon Glass
2019-10-21  7:48   ` Andy Shevchenko
2019-10-21 22:53     ` Simon Glass
2019-10-22  8:21       ` Andy Shevchenko
2019-10-22 13:50         ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 036/108] pci: Add support for p2sb uclass Simon Glass
2019-11-04  8:23   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 037/108] sandbox: Add PCI driver and test for p2sb Simon Glass
2019-11-04  8:36   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 038/108] x86: Move UCLASS_IRQ into a separate file Simon Glass
2019-11-04  8:41   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 039/108] sandbox: Add a test for IRQ Simon Glass
2019-11-04  8:45   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 040/108] x86: Define the SPL image start Simon Glass
2019-11-04  8:46   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 041/108] x86: Reduce mrccache record alignment size Simon Glass
2019-11-04  8:50   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 042/108] x86: Correct mrccache find_next_mrc_cache() calculation Simon Glass
2019-11-04 15:01   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 043/108] x86: Adjust mrccache_get_region() to use livetree Simon Glass
2019-11-04 15:06   ` Bin Meng
2019-11-12  0:51     ` Simon Glass
2019-11-13 15:16       ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 044/108] x86: Adjust mrccache_get_region() to support get_mmap() Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 045/108] x86: Add a new global_data member for the cache record Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 046/108] x86: Tidy up error handling in mrccache_save() Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 047/108] x86: Update mrccache to support multiple caches Simon Glass
2019-11-04 15:22   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 048/108] x86: Add mrccache support for a 'variable' cache Simon Glass
2019-11-04 15:23   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 049/108] x86: Move fsp_prepare_mrc_cache() to fsp1 directory Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 050/108] x86: Set the DRAM banks to reflect real location Simon Glass
2019-11-04 15:24   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 051/108] x86: Set up the MTRR for SDRAM Simon Glass
2019-11-19  2:23   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 052/108] x86: Don't imply libfdt or SPI flash in TPL Simon Glass
2019-11-19  2:23   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 053/108] x86: Allow removal of standard PCH drivers Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 054/108] x86: Allow interrupt to happen once Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 055/108] x86: fsp: Make graphics support common to FSP1/2 Simon Glass
2019-11-19  2:23   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 056/108] x86: fsp: Correct wrong header inlude in fsp_support.c Simon Glass
2019-11-19  7:25   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 057/108] x86: fsp: Add FSP2 base support Simon Glass
2019-11-19  7:25   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 058/108] x86: fsp: Set up an MTRR for the graphics frame buffer Simon Glass
2019-11-19  7:25   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 059/108] x86: fsp: Add a new arch_fsp_init_r() hook Simon Glass
2019-11-19  7:25   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 060/108] x86: fsp: Allow remembering the location of FSP-S Simon Glass
2019-11-19  7:25   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 061/108] x86: fsp: Make the notify API call common Simon Glass
2019-11-19  8:02   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 062/108] x86: Don't include the BIOS emulator in TPL Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 063/108] x86: Add an option to include a FIT Simon Glass
2019-11-19  8:02   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 064/108] x86: Add support for newer CAR schemes Simon Glass
2019-10-21  8:11   ` Andy Shevchenko
2019-11-19  8:02   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 065/108] x86: Disable microcode section for FSP2 Simon Glass
2019-11-19  8:02   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 066/108] x86: Update the fsp command " Simon Glass
2019-11-19  8:34   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 067/108] x86: Update .dtsi file " Simon Glass
2019-11-19  8:34   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 068/108] x86: Add an option to control the position of U-Boot Simon Glass
2019-11-19  8:34   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 069/108] x86: Add an option to control the position of SPL Simon Glass
2019-11-19  8:34   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 070/108] x86: Add an fdtmap and image-header Simon Glass
2019-11-19  8:34   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 071/108] x86: Don't repeat microcode in U-Boot if not needed Simon Glass
2019-11-19 13:33   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 072/108] x86: Separate out U-Boot and device tree in ROM image Simon Glass
2019-11-19 13:33   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 073/108] x86: Make MSR_PKG_POWER_SKU common Simon Glass
2019-11-19 13:33   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 074/108] spi: Correct operations check in dm_spi_xfer() Simon Glass
2019-11-19 13:33   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 075/108] x86: spi: Don't enable SPI_FLASH_BAR by default Simon Glass
2019-11-19 13:33   ` Bin Meng
2019-11-20  5:22     ` Vignesh Raghavendra
2019-11-21 13:50       ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 076/108] spi: ich: Move init function just above probe() Simon Glass
2019-11-19 13:52   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 077/108] spi: ich: Move the protection/lockdown code into a function Simon Glass
2019-11-19 13:53   ` Bin Meng
2019-11-19 17:53     ` Simon Glass
2019-11-20 12:55       ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 078/108] spi: ich: Convert to livetree Simon Glass
2019-11-19 13:53   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 079/108] spi: ich: Fix header order Simon Glass
2019-11-19 13:53   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 080/108] spi: ich: Various small tidy-ups Simon Glass
2019-11-19 13:53   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 081/108] spi: ich: Add mmio_base to struct ich_spi_platdata Simon Glass
2019-11-19 14:36   ` Bin Meng
2019-11-19 17:53     ` Simon Glass
2019-11-20 12:52       ` Bin Meng
2019-11-21 13:50         ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 082/108] spi: ich: Correct max-size bug in ich_spi_adjust_size() Simon Glass
2019-11-19 14:36   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-11-21 14:04       ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 083/108] spi: ich: Support of-platdata for fast-spi Simon Glass
2019-11-19 14:36   ` Bin Meng
2019-11-19 17:53     ` Simon Glass
2019-11-20 12:48       ` Bin Meng
2019-11-21 13:50         ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 084/108] spi: ich: Support hardware sequencing Simon Glass
2019-11-19 14:36   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 085/108] spi: ich: Add support for get_mmap() method Simon Glass
2019-11-19 14:36   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 086/108] spi: ich: Add TPL support Simon Glass
2019-11-19 14:52   ` Bin Meng
2019-11-21 13:50     ` Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 087/108] spi: ich: Add Apollolake support Simon Glass
2019-11-19 14:52   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 088/108] mtd: spi: Export spi_flash_std_probe() Simon Glass
2019-11-19 14:52   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 089/108] x86: apollolake: Add basic IO addresses Simon Glass
2019-11-19 14:52   ` Bin Meng
2019-10-21  3:38 ` [U-Boot] [PATCH v3 090/108] x86: apollolake: Add PMC driver Simon Glass
2019-10-21  3:38 ` [U-Boot] [PATCH v3 091/108] x86: apollolake: Add low-power subsystem (lpss) support Simon Glass
2019-10-21  8:14   ` Andy Shevchenko
2019-10-21  3:38 ` [U-Boot] [PATCH v3 092/108] x86: apollolake: Add UART driver Simon Glass
2019-10-21  7:46   ` Andy Shevchenko
2019-10-21 22:53     ` Simon Glass
2019-10-22  8:21       ` Andy Shevchenko
2019-10-21  3:38 ` [U-Boot] [PATCH v3 093/108] x86: apollolake: Add GPIO driver Simon Glass
2019-10-21  7:57   ` Andy Shevchenko
2019-10-21  3:38 ` [U-Boot] [PATCH v3 094/108] i2c: designware: Add apollolake support Simon Glass
2019-10-28  4:47   ` Heiko Schocher
2019-10-21  3:39 ` [U-Boot] [PATCH v3 095/108] x86: apollolake: Add systemagent driver Simon Glass
2019-10-21  8:16   ` Andy Shevchenko
2019-10-21  3:39 ` [U-Boot] [PATCH v3 096/108] x86: apollolake: Add hostbridge driver Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 097/108] x86: apollolake: Add ITSS driver Simon Glass
2019-10-21  8:41   ` Andy Shevchenko
2019-10-21  8:43     ` Andy Shevchenko
2019-10-21 22:53       ` Simon Glass
2019-10-22  8:22         ` Andy Shevchenko
2019-10-22 13:50           ` Simon Glass
2019-10-22 18:56             ` Andy Shevchenko
2019-10-21  3:39 ` [U-Boot] [PATCH v3 098/108] x86: apollolake: Add LPC driver Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 099/108] x86: apollolake: Add PCH driver Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 100/108] x86: apollolake: Add PUNIT driver Simon Glass
2019-10-21  8:47   ` Andy Shevchenko
2019-10-21  3:39 ` [U-Boot] [PATCH v3 101/108] x86: apollolake: Add SPL loaders Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 102/108] x86: apollolake: Add a CPU driver Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 103/108] x86: apollolake: Add SPL/TPL init Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 104/108] x86: apollolake: Add P2SB driver Simon Glass
2019-10-21  8:49   ` Andy Shevchenko
2019-10-21 22:53     ` Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 105/108] x86: apollolake: Add Kconfig and Makefile Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 106/108] x86: apollolake: Add FSP structures Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 107/108] x86: apollolake: Add FSP support Simon Glass
2019-10-21  3:39 ` [U-Boot] [PATCH v3 108/108] x86: Add chromebook_coral Simon Glass
2019-10-21 19:15 ` [U-Boot] [PATCH v3 022/108] x86: timer: Use a separate flag for whether timer is inited Park, Aiden
2019-10-28  7:12 ` Bin Meng
2019-11-02  9:47   ` Bin Meng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.