x86: ivybridge: Add PCH init
authorSimon Glass <sjg@chromium.org>
Sat, 15 Nov 2014 01:18:34 +0000 (18:18 -0700)
committerSimon Glass <sjg@chromium.org>
Tue, 25 Nov 2014 13:34:00 +0000 (06:34 -0700)
Add required init for the Intel Platform Controller Hub in ivybridge.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/x86/cpu/ivybridge/Makefile
arch/x86/cpu/ivybridge/pch.c [new file with mode: 0644]
arch/x86/include/asm/arch-ivybridge/pch.h

index b37fb8f..479e446 100644 (file)
@@ -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 (file)
index 0000000..fa04d48
--- /dev/null
@@ -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;
+}
index aa626ad..b3ec7c5 100644 (file)
 
 #include <pci.h>
 
+/* PCH types */
+#define PCH_TYPE_CPT   0x1c /* CougarPoint */
+#define PCH_TYPE_PPT   0x1e /* IvyBridge */
+
+/* PCH stepping values for LPC device */
+#define PCH_STEP_A0    0
+#define PCH_STEP_A1    1
+#define PCH_STEP_B0    2
+#define PCH_STEP_B1    3
+#define PCH_STEP_B2    4
+#define PCH_STEP_B3    5
 #define DEFAULT_GPIOBASE       0x0480
 #define DEFAULT_PMBASE         0x0500
 
 #define SMBUS_IO_BASE          0x0400
 
+int pch_silicon_revision(void);
+int pch_silicon_type(void);
+int pch_silicon_supported(int type, int rev);
+void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
+
+#define MAINBOARD_POWER_OFF    0
+#define MAINBOARD_POWER_ON     1
+#define MAINBOARD_POWER_KEEP   2
+
 /* PCI Configuration Space (D30:F0): PCI2PCI */
 #define PSTS   0x06
 #define SMLT   0x1b
 
 /* PCI Configuration Space (D31:F0): LPC */
 #define PCH_LPC_DEV            PCI_BDF(0, 0x1f, 0)
+#define SERIRQ_CNTL            0x64
+
+#define GEN_PMCON_1            0xa0
+#define GEN_PMCON_2            0xa2
+#define GEN_PMCON_3            0xa4
+#define ETR3                   0xac
+#define  ETR3_CWORWRE          (1 << 18)
+#define  ETR3_CF9GR            (1 << 20)
+
+/* GEN_PMCON_3 bits */
+#define RTC_BATTERY_DEAD       (1 << 2)
+#define RTC_POWER_FAILED       (1 << 1)
+#define SLEEP_AFTER_POWER_FAIL (1 << 0)
+
+#define PMBASE                 0x40
+#define ACPI_CNTL              0x44
+#define BIOS_CNTL              0xDC
+#define GPIO_BASE              0x48 /* LPC GPIO Base Address Register */
+#define GPIO_CNTL              0x4C /* LPC GPIO Control Register */
+#define GPIO_ROUT              0xb8
+
+#define PIRQA_ROUT             0x60
+#define PIRQB_ROUT             0x61
+#define PIRQC_ROUT             0x62
+#define PIRQD_ROUT             0x63
+#define PIRQE_ROUT             0x68
+#define PIRQF_ROUT             0x69
+#define PIRQG_ROUT             0x6A
+#define PIRQH_ROUT             0x6B
 
 #define GEN_PMCON_1            0xa0
 #define GEN_PMCON_2            0xa2