summaryrefslogtreecommitdiff
path: root/arch/x86/cpu
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-11-14 18:18:34 -0700
committerSimon Glass <sjg@chromium.org>2014-11-25 06:34:00 -0700
commit8c74a57318d1302d28a10ae862a7faa9086e2660 (patch)
tree1d8dd7c707765cf936d8173885b73a8e650e94e1 /arch/x86/cpu
parent3e0332c0b90323ca3c0584e9ae5592b04b121bae (diff)
downloadu-boot-imx-8c74a57318d1302d28a10ae862a7faa9086e2660.zip
u-boot-imx-8c74a57318d1302d28a10ae862a7faa9086e2660.tar.gz
u-boot-imx-8c74a57318d1302d28a10ae862a7faa9086e2660.tar.bz2
x86: ivybridge: Add PCH init
Add required init for the Intel Platform Controller Hub in ivybridge. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r--arch/x86/cpu/ivybridge/Makefile1
-rw-r--r--arch/x86/cpu/ivybridge/pch.c123
2 files changed, 124 insertions, 0 deletions
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
index b37fb8f..479e446 100644
--- a/arch/x86/cpu/ivybridge/Makefile
+++ b/arch/x86/cpu/ivybridge/Makefile
@@ -12,6 +12,7 @@ obj-y += early_me.o
obj-y += lpc.o
obj-y += me_status.o
obj-y += microcode_intel.o
+obj-y += pch.o
obj-y += pci.o
obj-y += report_platform.o
obj-y += sdram.o
diff --git a/arch/x86/cpu/ivybridge/pch.c b/arch/x86/cpu/ivybridge/pch.c
new file mode 100644
index 0000000..fa04d48
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/pch.c
@@ -0,0 +1,123 @@
+/*
+ * From Coreboot
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2012 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+static int pch_revision_id = -1;
+static int pch_type = -1;
+
+int pch_silicon_revision(void)
+{
+ pci_dev_t dev;
+
+ dev = PCH_LPC_DEV;
+
+ if (pch_revision_id < 0)
+ pch_revision_id = pci_read_config8(dev, PCI_REVISION_ID);
+ return pch_revision_id;
+}
+
+int pch_silicon_type(void)
+{
+ pci_dev_t dev;
+
+ dev = PCH_LPC_DEV;
+
+ if (pch_type < 0)
+ pch_type = pci_read_config8(dev, PCI_DEVICE_ID + 1);
+ return pch_type;
+}
+
+int pch_silicon_supported(int type, int rev)
+{
+ int cur_type = pch_silicon_type();
+ int cur_rev = pch_silicon_revision();
+
+ switch (type) {
+ case PCH_TYPE_CPT:
+ /* CougarPoint minimum revision */
+ if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
+ return 1;
+ /* PantherPoint any revision */
+ if (cur_type == PCH_TYPE_PPT)
+ return 1;
+ break;
+
+ case PCH_TYPE_PPT:
+ /* PantherPoint minimum revision */
+ if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+#define IOBP_RETRY 1000
+static inline int iobp_poll(void)
+{
+ unsigned try = IOBP_RETRY;
+ u32 data;
+
+ while (try--) {
+ data = readl(RCB_REG(IOBPS));
+ if ((data & 1) == 0)
+ return 1;
+ udelay(10);
+ }
+
+ printf("IOBP timeout\n");
+ return 0;
+}
+
+void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
+{
+ u32 data;
+
+ /* Set the address */
+ writel(address, RCB_REG(IOBPIRI));
+
+ /* READ OPCODE */
+ if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
+ writel(IOBPS_RW_BX, RCB_REG(IOBPS));
+ else
+ writel(IOBPS_READ_AX, RCB_REG(IOBPS));
+ if (!iobp_poll())
+ return;
+
+ /* Read IOBP data */
+ data = readl(RCB_REG(IOBPD));
+ if (!iobp_poll())
+ return;
+
+ /* Check for successful transaction */
+ if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
+ printf("IOBP read 0x%08x failed\n", address);
+ return;
+ }
+
+ /* Update the data */
+ data &= andvalue;
+ data |= orvalue;
+
+ /* WRITE OPCODE */
+ if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
+ writel(IOBPS_RW_BX, RCB_REG(IOBPS));
+ else
+ writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
+ if (!iobp_poll())
+ return;
+
+ /* Write IOBP data */
+ writel(data, RCB_REG(IOBPD));
+ if (!iobp_poll())
+ return;
+}