xref: /openbmc/u-boot/arch/x86/cpu/queensbay/tnc.c (revision 2b94d9fca2bef8cffd5ad56f609aed1f0d024900)
1b2e02d28SBin Meng /*
2b2e02d28SBin Meng  * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
3b2e02d28SBin Meng  *
4b2e02d28SBin Meng  * SPDX-License-Identifier:	GPL-2.0+
5b2e02d28SBin Meng  */
6b2e02d28SBin Meng 
7b2e02d28SBin Meng #include <common.h>
8*2b94d9fcSBin Meng #include <dm.h>
9*2b94d9fcSBin Meng #include <pci.h>
10b2e02d28SBin Meng #include <asm/io.h>
119c7dea60SBin Meng #include <asm/irq.h>
12b2e02d28SBin Meng #include <asm/post.h>
13afbf1404SBin Meng #include <asm/arch/device.h>
149c7dea60SBin Meng #include <asm/arch/tnc.h>
151021af4dSSimon Glass #include <asm/fsp/fsp_support.h>
16b2e02d28SBin Meng #include <asm/processor.h>
17b2e02d28SBin Meng 
189e36c53dSBin Meng static int __maybe_unused disable_igd(void)
191f124ebaSBin Meng {
20*2b94d9fcSBin Meng 	struct udevice *igd, *sdvo;
21*2b94d9fcSBin Meng 	int ret;
22*2b94d9fcSBin Meng 
23*2b94d9fcSBin Meng 	ret = dm_pci_bus_find_bdf(TNC_IGD, &igd);
24*2b94d9fcSBin Meng 	if (ret)
25*2b94d9fcSBin Meng 		return ret;
26*2b94d9fcSBin Meng 	if (!igd)
27*2b94d9fcSBin Meng 		return 0;
28*2b94d9fcSBin Meng 
29*2b94d9fcSBin Meng 	ret = dm_pci_bus_find_bdf(TNC_SDVO, &sdvo);
30*2b94d9fcSBin Meng 	if (ret)
31*2b94d9fcSBin Meng 		return ret;
32*2b94d9fcSBin Meng 	if (!sdvo)
33*2b94d9fcSBin Meng 		return 0;
34*2b94d9fcSBin Meng 
35e5ffa4bbSBin Meng 	/*
36e5ffa4bbSBin Meng 	 * According to Atom E6xx datasheet, setting VGA Disable (bit17)
37e5ffa4bbSBin Meng 	 * of Graphics Controller register (offset 0x50) prevents IGD
38e5ffa4bbSBin Meng 	 * (D2:F0) from reporting itself as a VGA display controller
39e5ffa4bbSBin Meng 	 * class in the PCI configuration space, and should also prevent
40e5ffa4bbSBin Meng 	 * it from responding to VGA legacy memory range and I/O addresses.
41e5ffa4bbSBin Meng 	 *
42e5ffa4bbSBin Meng 	 * However test result shows that with just VGA Disable bit set and
43e5ffa4bbSBin Meng 	 * a PCIe graphics card connected to one of the PCIe controllers on
44e5ffa4bbSBin Meng 	 * the E6xx, accessing the VGA legacy space still causes system hang.
45e5ffa4bbSBin Meng 	 * After a number of attempts, it turns out besides VGA Disable bit,
46e5ffa4bbSBin Meng 	 * the SDVO (D3:F0) device should be disabled to make it work.
47e5ffa4bbSBin Meng 	 *
48e5ffa4bbSBin Meng 	 * To simplify, use the Function Disable register (offset 0xc4)
49e5ffa4bbSBin Meng 	 * to disable both IGD (D2:F0) and SDVO (D3:F0) devices. Now these
50e5ffa4bbSBin Meng 	 * two devices will be completely disabled (invisible in the PCI
51e5ffa4bbSBin Meng 	 * configuration space) unless a system reset is performed.
52e5ffa4bbSBin Meng 	 */
53*2b94d9fcSBin Meng 	dm_pci_write_config32(igd, IGD_FD, FUNC_DISABLE);
54*2b94d9fcSBin Meng 	dm_pci_write_config32(sdvo, IGD_FD, FUNC_DISABLE);
559e36c53dSBin Meng 
569e36c53dSBin Meng 	return 0;
571f124ebaSBin Meng }
581f124ebaSBin Meng 
59b2e02d28SBin Meng int arch_cpu_init(void)
60b2e02d28SBin Meng {
61adfe3b24SBin Meng 	int ret;
62adfe3b24SBin Meng 
63b2e02d28SBin Meng 	post_code(POST_CPU_INIT);
64b2e02d28SBin Meng 
65adfe3b24SBin Meng 	ret = x86_cpu_init_f();
66adfe3b24SBin Meng 	if (ret)
67adfe3b24SBin Meng 		return ret;
68adfe3b24SBin Meng 
69adfe3b24SBin Meng 	return 0;
70b2e02d28SBin Meng }
71afbf1404SBin Meng 
721f124ebaSBin Meng int arch_early_init_r(void)
731f124ebaSBin Meng {
749e36c53dSBin Meng 	int ret = 0;
759e36c53dSBin Meng 
761f124ebaSBin Meng #ifdef CONFIG_DISABLE_IGD
779e36c53dSBin Meng 	ret = disable_igd();
781f124ebaSBin Meng #endif
791f124ebaSBin Meng 
809e36c53dSBin Meng 	return ret;
811f124ebaSBin Meng }
82