aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/cpu
diff options
context:
space:
mode:
authorBin Meng2016-02-01 01:40:55 -0800
committerBin Meng2016-02-05 12:47:22 +0800
commit66484f0fc01ab3c65007c869f563adc04aa5c175 (patch)
tree3b232e567b172fe64a5e4abdf565aa9db2b342e2 /arch/x86/cpu
parent2b94d9fca2bef8cffd5ad56f609aed1f0d024900 (diff)
x86: tnc: Remove IGD and SDVO devices from driver model
With recent DM PCI changes to vesa_fb driver, external graphics card does not work any more. This is because: after setting the function disable bit, IGD and SDVO devices will disappear in the PCI configuration space. This however creates an inconsistent state from a driver model PCI controller point of view, as these two PCI devices are still attached to its parent's child device list as maintained by the driver model. Some driver model PCI APIs like dm_pci_find_class() used in the vesa_fb driver, are referring to the list to speed up the finding process instead of re-enumerating the whole PCI bus, so it gets the stale cached data which is wrong. To fix this, manually remove these two devices. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r--arch/x86/cpu/queensbay/tnc.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 38082c4a779..b226e4c5fd6 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <dm.h>
+#include <dm/device-internal.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -53,6 +54,41 @@ static int __maybe_unused disable_igd(void)
dm_pci_write_config32(igd, IGD_FD, FUNC_DISABLE);
dm_pci_write_config32(sdvo, IGD_FD, FUNC_DISABLE);
+ /*
+ * After setting the function disable bit, IGD and SDVO devices will
+ * disappear in the PCI configuration space. This however creates an
+ * inconsistent state from a driver model PCI controller point of view,
+ * as these two PCI devices are still attached to its parent's child
+ * device list as maintained by the driver model. Some driver model PCI
+ * APIs like dm_pci_find_class(), are referring to the list to speed up
+ * the finding process instead of re-enumerating the whole PCI bus, so
+ * it gets the stale cached data which is wrong.
+ *
+ * Note x86 PCI enueration normally happens twice, in pre-relocation
+ * phase and post-relocation. One option might be to call disable_igd()
+ * in one of the pre-relocation initialization hooks so that it gets
+ * disabled in the first round, and when it comes to the second round
+ * driver model PCI will construct a correct list. Unfortunately this
+ * does not work as Intel FSP is used on this platform to perform low
+ * level initialization, and fsp_init_phase_pci() is called only once
+ * in the post-relocation phase. If we disable IGD and SDVO devices,
+ * fsp_init_phase_pci() simply hangs and never returns.
+ *
+ * So the only option we have is to manually remove these two devices.
+ */
+ ret = device_remove(igd);
+ if (ret)
+ return ret;
+ ret = device_unbind(igd);
+ if (ret)
+ return ret;
+ ret = device_remove(sdvo);
+ if (ret)
+ return ret;
+ ret = device_unbind(sdvo);
+ if (ret)
+ return ret;
+
return 0;
}