summaryrefslogtreecommitdiff
path: root/arch/x86
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2015-09-03 05:37:25 -0700
committerSimon Glass <sjg@chromium.org>2015-09-09 07:48:03 -0600
commit316fd3920f67fa8d3ca25a81ceead546464145fa (patch)
tree71864f4babbb9856444ebf1a3d10f521bdc63246 /arch/x86
parentaa09505ba1677c25e83115375a6775a5eae444ef (diff)
x86: Enable PCIe controller on quark/galileo
Quark SoC holds the PCIe controller in reset following a power on. U-Boot needs to release the PCIe controller from reset. The PCIe controller (D23:F0/F1) will not be visible in PCI configuration space and any access to its PCI configuration registers will cause system hang while it is held in reset. Enable PCIe controller per Quark firmware writer guide. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/cpu/quark/quark.c63
-rw-r--r--arch/x86/include/asm/arch-quark/quark.h42
2 files changed, 105 insertions, 0 deletions
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c
index 2688a707a7..7c55d9e5cd 100644
--- a/arch/x86/cpu/quark/quark.c
+++ b/arch/x86/cpu/quark/quark.c
@@ -73,6 +73,58 @@ static void quark_setup_bars(void)
CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
}
+static void quark_pcie_early_init(void)
+{
+ u32 pcie_cfg;
+
+ /*
+ * Step1: Assert PCIe signal PERST#
+ *
+ * The CPU interface to the PERST# signal is platform dependent.
+ * Call the board-specific codes to perform this task.
+ */
+ board_assert_perst();
+
+ /* Step2: PHY common lane reset */
+ pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+ pcie_cfg |= PCIE_PHY_LANE_RST;
+ msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+ /* wait 1 ms for PHY common lane reset */
+ mdelay(1);
+
+ /* Step3: PHY sideband interface reset and controller main reset */
+ pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+ pcie_cfg |= (PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST);
+ msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+ /* wait 80ms for PLL to lock */
+ mdelay(80);
+
+ /* Step4: Controller sideband interface reset */
+ pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+ pcie_cfg |= PCIE_CTLR_SB_RST;
+ msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+ /* wait 20ms for controller sideband interface reset */
+ mdelay(20);
+
+ /* Step5: De-assert PERST# */
+ board_deassert_perst();
+
+ /* Step6: Controller primary interface reset */
+ pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+ pcie_cfg |= PCIE_CTLR_PRI_RST;
+ msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+
+ /* Mixer Load Lane 0 */
+ pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0);
+ pcie_cfg &= ~((1 << 6) | (1 << 7));
+ msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0, pcie_cfg);
+
+ /* Mixer Load Lane 1 */
+ pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1);
+ pcie_cfg &= ~((1 << 6) | (1 << 7));
+ msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg);
+}
+
static void quark_enable_legacy_seg(void)
{
u32 hmisc2;
@@ -106,6 +158,17 @@ int arch_cpu_init(void)
*/
quark_setup_bars();
+ /*
+ * Initialize PCIe controller
+ *
+ * Quark SoC holds the PCIe controller in reset following a power on.
+ * U-Boot needs to release the PCIe controller from reset. The PCIe
+ * controller (D23:F0/F1) will not be visible in PCI configuration
+ * space and any access to its PCI configuration registers will cause
+ * system hang while it is held in reset.
+ */
+ quark_pcie_early_init();
+
/* Turn on legacy segments (A/B/E/F) decode to system RAM */
quark_enable_legacy_seg();
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h
index 1ce56934d6..aad7fbe883 100644
--- a/arch/x86/include/asm/arch-quark/quark.h
+++ b/arch/x86/include/asm/arch-quark/quark.h
@@ -12,6 +12,7 @@
#define MSG_PORT_HOST_BRIDGE 0x03
#define MSG_PORT_RMU 0x04
#define MSG_PORT_MEM_MGR 0x05
+#define MSG_PORT_PCIE_AFE 0x16
#define MSG_PORT_SOC_UNIT 0x31
/* Port 0x00: Memory Arbiter Message Port Registers */
@@ -48,6 +49,21 @@
#define ESRAM_BLK_CTRL 0x82
#define ESRAM_BLOCK_MODE 0x10000000
+/* Port 0x16: PCIe AFE Unit Port Registers */
+
+#define PCIE_RXPICTRL0_L0 0x2080
+#define PCIE_RXPICTRL0_L1 0x2180
+
+/* Port 0x31: SoC Unit Port Registers */
+
+/* PCIe Controller Config */
+#define PCIE_CFG 0x36
+#define PCIE_CTLR_PRI_RST 0x00010000
+#define PCIE_PHY_SB_RST 0x00020000
+#define PCIE_CTLR_SB_RST 0x00040000
+#define PCIE_PHY_LANE_RST 0x00090000
+#define PCIE_CTLR_MAIN_RST 0x00100000
+
/* DRAM */
#define DRAM_BASE 0x00000000
#define DRAM_MAX_SIZE 0x80000000
@@ -124,6 +140,32 @@ static inline void qrk_pci_write_config_dword(pci_dev_t dev, int offset,
outl(value, PCI_REG_DATA);
}
+/**
+ * board_assert_perst() - Assert the PERST# pin
+ *
+ * The CPU interface to the PERST# signal on Quark is platform dependent.
+ * Board-specific codes need supply this routine to assert PCIe slot reset.
+ *
+ * The tricky part in this routine is that any APIs that may trigger PCI
+ * enumeration process are strictly forbidden, as any access to PCIe root
+ * port's configuration registers will cause system hang while it is held
+ * in reset.
+ */
+void board_assert_perst(void);
+
+/**
+ * board_deassert_perst() - De-assert the PERST# pin
+ *
+ * The CPU interface to the PERST# signal on Quark is platform dependent.
+ * Board-specific codes need supply this routine to de-assert PCIe slot reset.
+ *
+ * The tricky part in this routine is that any APIs that may trigger PCI
+ * enumeration process are strictly forbidden, as any access to PCIe root
+ * port's configuration registers will cause system hang while it is held
+ * in reset.
+ */
+void board_deassert_perst(void);
+
#endif /* __ASSEMBLY__ */
#endif /* _QUARK_H_ */