summaryrefslogtreecommitdiff
path: root/arch/x86
diff options
context:
space:
mode:
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 2688a70..7c55d9e 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 1ce5693..aad7fbe 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_ */