From fadfc2e2f6abbcaea7bbc92c13716c5382443993 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Fri, 1 Jul 2016 16:36:03 -0500 Subject: [PATCH] soc/intel/apollolake: handle p2sb quirks The P2SB device is device 0xd and function 0. If hidden that causes the latter pci devices on function >= 1 to not be probed in the kernel. This is also a problem for coreboot if the P2SB device is hidden by FSP. That means the coreboot driver won't be ran. Therefore, provide hide and unhide functions for the P2SB device. The other quirk is to allow the GPIO devices to work correctly. Those devices are ACPI devices. However, their resources are sub-regions within the P2SB BAR. Sadly, linux doesn't handle ACPI devices being children of PCI devices. This leads to resource conflict errors when the P2SB device is visible. For the time being keep the P2SB device hidden, but also ensure the resources it is using are accounted for and reserved. The fallout of that is the PMC and SPI device are no longer probed by the kernel. BUG=chrome-os-partner:53017 TEST=Ensured P2SB device is visible and pci resources are allocated correctly for the devices. Change-Id: I24e59bbde74310e1ce8425b344a3ad0b88702153 Signed-off-by: Aaron Durbin Reviewed-on: https://review.coreboot.org/15530 Tested-by: build bot (Jenkins) Reviewed-by: Andrey Petrov Reviewed-by: Furquan Shaikh --- src/soc/intel/apollolake/Makefile.inc | 1 + src/soc/intel/apollolake/chip.c | 14 +++- src/soc/intel/apollolake/include/soc/iomap.h | 3 + src/soc/intel/apollolake/include/soc/p2sb.h | 23 ++++++ src/soc/intel/apollolake/p2sb.c | 74 ++++++++++++++++++++ 5 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/soc/intel/apollolake/include/soc/p2sb.h create mode 100644 src/soc/intel/apollolake/p2sb.c diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc index a64ee78328..9fbb82d975 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -52,6 +52,7 @@ ramstage-y += lpc.c ramstage-y += lpc_lib.c ramstage-y += memmap.c ramstage-y += mmap_boot.c +ramstage-y += p2sb.c ramstage-y += uart.c ramstage-y += nhlt.c ramstage-y += northbridge.c diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index 68459e602a..00470a201a 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "chip.h" @@ -153,6 +154,14 @@ static void soc_init(void *data) range_entry_init(&range, 0x200000, 4ULL*GiB, 0); fsp_silicon_init(&range); + /* + * Keep the P2SB device visible so it and the other devices are + * visible in coreboot for driver support and PCI resource allocation. + * There is a UPD setting for this, but it's more consistent to use + * hide and unhide symmetrically. + */ + p2sb_unhide(); + /* Allocate ACPI NVS in CBMEM */ gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs)); } @@ -346,8 +355,11 @@ static void fsp_notify_dummy(void *arg) fsp_handle_reset(ret); } /* Call END_OF_FIRMWARE Notify after READY_TO_BOOT Notify */ - if (ph == READY_TO_BOOT) + if (ph == READY_TO_BOOT) { fsp_notify_dummy((void *)END_OF_FIRMWARE); + /* Hide the P2SB device to align with previous behavior. */ + p2sb_hide(); + } } BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT, fsp_notify_dummy, diff --git a/src/soc/intel/apollolake/include/soc/iomap.h b/src/soc/intel/apollolake/include/soc/iomap.h index e9caecac7a..2045434e6e 100644 --- a/src/soc/intel/apollolake/include/soc/iomap.h +++ b/src/soc/intel/apollolake/include/soc/iomap.h @@ -18,7 +18,10 @@ #ifndef _SOC_APOLLOLAKE_IOMAP_H_ #define _SOC_APOLLOLAKE_IOMAP_H_ +#include + #define P2SB_BAR CONFIG_IOSF_BASE_ADDRESS +#define P2SB_SIZE (16 * MiB) #define MCH_BASE_ADDR 0xfed10000 #define MCH_BASE_SIZE (32 * KiB) diff --git a/src/soc/intel/apollolake/include/soc/p2sb.h b/src/soc/intel/apollolake/include/soc/p2sb.h new file mode 100644 index 0000000000..a0bcc67f45 --- /dev/null +++ b/src/soc/intel/apollolake/include/soc/p2sb.h @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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_P2SB_H_ +#define _SOC_APOLLOLAKE_P2SB_H_ + +void p2sb_unhide(void); +void p2sb_hide(void); + +#endif /* _SOC_APOLLOLAKE_P2SB_H_ */ diff --git a/src/soc/intel/apollolake/p2sb.c b/src/soc/intel/apollolake/p2sb.c new file mode 100644 index 0000000000..7834e3866e --- /dev/null +++ b/src/soc/intel/apollolake/p2sb.c @@ -0,0 +1,74 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define P2SB_E0 0xe0 +#define HIDE_BIT (1 << 0) + +static void p2sb_set_hide_bit(int hide) +{ + struct device *dev; + const uint16_t reg = P2SB_E0 + 1; + const uint8_t mask = HIDE_BIT; + uint8_t val; + + dev = P2SB_DEV; + + val = pci_read_config8(dev, reg); + val &= ~mask; + if (hide) + val |= mask; + pci_write_config8(dev, reg, val); +} + +void p2sb_unhide(void) +{ + p2sb_set_hide_bit(0); +} + +void p2sb_hide(void) +{ + p2sb_set_hide_bit(HIDE_BIT); +} + +static void read_resources(struct device *dev) +{ + /* + * There's only one resource on the P2SB device. It's also already + * manually set to a fixed address in earlier boot stages. + */ + mmio_resource(dev, PCI_BASE_ADDRESS_0, P2SB_BAR / KiB, P2SB_SIZE / KiB); +} + +static const struct device_operations device_ops = { + .read_resources = read_resources, + .set_resources = DEVICE_NOOP, +}; + +static const struct pci_driver pmc __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_APOLLOLAKE_P2SB, +};