aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/pch
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/pch')
-rw-r--r--roms/u-boot/drivers/pch/Kconfig27
-rw-r--r--roms/u-boot/drivers/pch/Makefile6
-rw-r--r--roms/u-boot/drivers/pch/pch-uclass.c70
-rw-r--r--roms/u-boot/drivers/pch/pch7.c88
-rw-r--r--roms/u-boot/drivers/pch/pch9.c87
-rw-r--r--roms/u-boot/drivers/pch/sandbox_pch.c86
6 files changed, 364 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/pch/Kconfig b/roms/u-boot/drivers/pch/Kconfig
new file mode 100644
index 000000000..c49a92885
--- /dev/null
+++ b/roms/u-boot/drivers/pch/Kconfig
@@ -0,0 +1,27 @@
+config PCH
+ bool "Enable Platform-controller Hub (PCH) support"
+ depends on X86 || SANDBOX
+ help
+ Most x86 chips include a PCH which is responsible for handling
+ parts of the system not handled by that CPU. It supersedes the
+ 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/roms/u-boot/drivers/pch/Makefile b/roms/u-boot/drivers/pch/Makefile
new file mode 100644
index 000000000..d5de3e48b
--- /dev/null
+++ b/roms/u-boot/drivers/pch/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += pch-uclass.o
+obj-$(CONFIG_X86_PCH7) += pch7.o
+obj-$(CONFIG_X86_PCH9) += pch9.o
+obj-$(CONFIG_SANDBOX) += sandbox_pch.o
diff --git a/roms/u-boot/drivers/pch/pch-uclass.c b/roms/u-boot/drivers/pch/pch-uclass.c
new file mode 100644
index 000000000..ad4906aa5
--- /dev/null
+++ b/roms/u-boot/drivers/pch/pch-uclass.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pch.h>
+
+int pch_get_spi_base(struct udevice *dev, ulong *sbasep)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ *sbasep = 0;
+ if (!ops->get_spi_base)
+ return -ENOSYS;
+
+ return ops->get_spi_base(dev, sbasep);
+}
+
+int pch_set_spi_protect(struct udevice *dev, bool protect)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ if (!ops->set_spi_protect)
+ return -ENOSYS;
+
+ return ops->set_spi_protect(dev, protect);
+}
+
+int pch_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ *gbasep = 0;
+ if (!ops->get_gpio_base)
+ return -ENOSYS;
+
+ return ops->get_gpio_base(dev, gbasep);
+}
+
+int pch_get_io_base(struct udevice *dev, u32 *iobasep)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ *iobasep = 0;
+ if (!ops->get_io_base)
+ return -ENOSYS;
+
+ return ops->get_io_base(dev, iobasep);
+}
+
+int pch_ioctl(struct udevice *dev, ulong req, void *data, int size)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ if (!ops->ioctl)
+ return -ENOSYS;
+
+ return ops->ioctl(dev, req, data, size);
+}
+
+UCLASS_DRIVER(pch) = {
+ .id = UCLASS_PCH,
+ .name = "pch",
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .post_bind = dm_scan_fdt_dev,
+#endif
+};
diff --git a/roms/u-boot/drivers/pch/pch7.c b/roms/u-boot/drivers/pch/pch7.c
new file mode 100644
index 000000000..5fb35a19e
--- /dev/null
+++ b/roms/u-boot/drivers/pch/pch7.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <pch.h>
+
+#define GPIO_BASE 0x44
+#define BIOS_CTRL 0xd8
+
+static int pch7_get_spi_base(struct udevice *dev, ulong *sbasep)
+{
+ u32 rcba;
+
+ dm_pci_read_config32(dev, PCH_RCBA, &rcba);
+ /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
+ rcba = rcba & 0xffffc000;
+ *sbasep = rcba + 0x3020;
+
+ return 0;
+}
+
+static int pch7_set_spi_protect(struct udevice *dev, bool protect)
+{
+ uint8_t bios_cntl;
+
+ /* Adjust the BIOS write protect to dis/allow write commands */
+ dm_pci_read_config8(dev, BIOS_CTRL, &bios_cntl);
+ if (protect)
+ bios_cntl &= ~BIOS_CTRL_BIOSWE;
+ else
+ bios_cntl |= BIOS_CTRL_BIOSWE;
+ dm_pci_write_config8(dev, BIOS_CTRL, bios_cntl);
+
+ return 0;
+}
+
+static int pch7_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ u32 base;
+
+ /*
+ * GPIO_BASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros.
+ *
+ * Note we don't need check bit0 here, because the Tunnel Creek
+ * GPIO base address register bit0 is reserved (read returns 0),
+ * while on the Ivybridge the bit0 is used to indicate it is an
+ * I/O space.
+ */
+ dm_pci_read_config32(dev, GPIO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ *gbasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
+}
+
+static const struct pch_ops pch7_ops = {
+ .get_spi_base = pch7_get_spi_base,
+ .set_spi_protect = pch7_set_spi_protect,
+ .get_gpio_base = pch7_get_gpio_base,
+};
+
+static const struct udevice_id pch7_ids[] = {
+ { .compatible = "intel,pch7" },
+ { }
+};
+
+U_BOOT_DRIVER(pch7_drv) = {
+ .name = "intel-pch7",
+ .id = UCLASS_PCH,
+ .of_match = pch7_ids,
+ .ops = &pch7_ops,
+};
diff --git a/roms/u-boot/drivers/pch/pch9.c b/roms/u-boot/drivers/pch/pch9.c
new file mode 100644
index 000000000..3bd011518
--- /dev/null
+++ b/roms/u-boot/drivers/pch/pch9.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <pch.h>
+
+#define GPIO_BASE 0x48
+#define IO_BASE 0x4c
+#define SBASE_ADDR 0x54
+
+static int pch9_get_spi_base(struct udevice *dev, ulong *sbasep)
+{
+ uint32_t sbase_addr;
+
+ dm_pci_read_config32(dev, SBASE_ADDR, &sbase_addr);
+ *sbasep = sbase_addr & 0xfffffe00;
+
+ return 0;
+}
+
+static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ u32 base;
+
+ /*
+ * GPIO_BASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros.
+ *
+ * Note we don't need check bit0 here, because the Tunnel Creek
+ * GPIO base address register bit0 is reserved (read returns 0),
+ * while on the Ivybridge the bit0 is used to indicate it is an
+ * I/O space.
+ */
+ dm_pci_read_config32(dev, GPIO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ *gbasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
+}
+
+static int pch9_get_io_base(struct udevice *dev, u32 *iobasep)
+{
+ u32 base;
+
+ dm_pci_read_config32(dev, IO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ *iobasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
+}
+
+static const struct pch_ops pch9_ops = {
+ .get_spi_base = pch9_get_spi_base,
+ .get_gpio_base = pch9_get_gpio_base,
+ .get_io_base = pch9_get_io_base,
+};
+
+static const struct udevice_id pch9_ids[] = {
+ { .compatible = "intel,pch9" },
+ { }
+};
+
+U_BOOT_DRIVER(pch9_drv) = {
+ .name = "intel-pch9",
+ .id = UCLASS_PCH,
+ .of_match = pch9_ids,
+ .ops = &pch9_ops,
+};
diff --git a/roms/u-boot/drivers/pch/sandbox_pch.c b/roms/u-boot/drivers/pch/sandbox_pch.c
new file mode 100644
index 000000000..37c368954
--- /dev/null
+++ b/roms/u-boot/drivers/pch/sandbox_pch.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pch.h>
+
+struct sandbox_pch_priv {
+ bool protect;
+};
+
+int sandbox_get_pch_spi_protect(struct udevice *dev)
+{
+ struct sandbox_pch_priv *priv = dev_get_priv(dev);
+
+ return priv->protect;
+}
+
+static int sandbox_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
+{
+ *sbasep = 0x10;
+
+ return 0;
+}
+
+static int sandbox_pch_set_spi_protect(struct udevice *dev, bool protect)
+{
+ struct sandbox_pch_priv *priv = dev_get_priv(dev);
+
+ priv->protect = protect;
+
+ return 0;
+}
+
+static int sandbox_pch_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ *gbasep = 0x20;
+
+ return 0;
+}
+
+static int sandbox_pch_get_io_base(struct udevice *dev, u32 *iobasep)
+{
+ *iobasep = 0x30;
+
+ return 0;
+}
+
+int sandbox_pch_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
+ int size)
+{
+ switch (req) {
+ case PCH_REQ_TEST1:
+ return -ENOSYS;
+ case PCH_REQ_TEST2:
+ return *(char *)data;
+ case PCH_REQ_TEST3:
+ *(char *)data = 'x';
+ return 1;
+ default:
+ return -ENOSYS;
+ }
+}
+
+static const struct pch_ops sandbox_pch_ops = {
+ .get_spi_base = sandbox_pch_get_spi_base,
+ .set_spi_protect = sandbox_pch_set_spi_protect,
+ .get_gpio_base = sandbox_pch_get_gpio_base,
+ .get_io_base = sandbox_pch_get_io_base,
+ .ioctl = sandbox_pch_ioctl,
+};
+
+static const struct udevice_id sandbox_pch_ids[] = {
+ { .compatible = "sandbox,pch" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_pch_drv) = {
+ .name = "sandbox-pch",
+ .id = UCLASS_PCH,
+ .of_match = sandbox_pch_ids,
+ .ops = &sandbox_pch_ops,
+ .priv_auto = sizeof(struct sandbox_pch_priv),
+};