diff options
Diffstat (limited to 'roms/u-boot/drivers/pch')
-rw-r--r-- | roms/u-boot/drivers/pch/Kconfig | 27 | ||||
-rw-r--r-- | roms/u-boot/drivers/pch/Makefile | 6 | ||||
-rw-r--r-- | roms/u-boot/drivers/pch/pch-uclass.c | 70 | ||||
-rw-r--r-- | roms/u-boot/drivers/pch/pch7.c | 88 | ||||
-rw-r--r-- | roms/u-boot/drivers/pch/pch9.c | 87 | ||||
-rw-r--r-- | roms/u-boot/drivers/pch/sandbox_pch.c | 86 |
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), +}; |