summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2014-07-15 14:19:03 +0800
committerRichard Zhu <r65037@freescale.com>2014-07-31 15:17:00 +0800
commitec78595a24b5ff1020baa97b6d6e79a3a3326307 (patch)
treeddb3512104efc1056df8fe1e6d145be363fcb672
parenta09f718e5ace202dd14426a030268ea11c7a9ba5 (diff)
downloadu-boot-imx-ec78595a24b5ff1020baa97b6d6e79a3a3326307.zip
u-boot-imx-ec78595a24b5ff1020baa97b6d6e79a3a3326307.tar.gz
u-boot-imx-ec78595a24b5ff1020baa97b6d6e79a3a3326307.tar.bz2
ENGR00325255 pcie:enable pcie support on imx6sx sd
Enable pcie support in uboot on imx6sx sd boards - enable_pcie_clock should be call before ssp_en is set, since that ssp_en control the phy_ref clk gate, turn on it after the source of the pcie clks are stable. - add debug info - add rx_eq of gpr12 on imx6sx - there are random link down issue on imx6sx. It's pcie ep reset issue. solution:reset ep, then retry link can fix it. Signed-off-by: Richard Zhu <r65037@freescale.com>
-rw-r--r--arch/arm/cpu/armv7/mx6/clock.c32
-rw-r--r--arch/arm/cpu/armv7/mx6/soc.c10
-rw-r--r--arch/arm/include/asm/arch-mx6/imx-regs.h2
-rw-r--r--arch/arm/include/asm/arch-mx6/iomux.h11
-rw-r--r--drivers/pci/pcie_imx.c139
-rw-r--r--include/configs/mx6sxsabresd.h10
6 files changed, 190 insertions, 14 deletions
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c
index abe2d81..700d190 100644
--- a/arch/arm/cpu/armv7/mx6/clock.c
+++ b/arch/arm/cpu/armv7/mx6/clock.c
@@ -733,6 +733,15 @@ static void ungate_sata_clock(void)
/* Enable SATA clock. */
setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
}
+#else
+static void ungate_disp_axi_clock(void)
+{
+ struct mxc_ccm_reg *const imx_ccm =
+ (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ /* Enable display axi clock. */
+ setbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_DISP_AXI_MASK);
+}
#endif
static void ungate_pcie_clock(void)
@@ -758,6 +767,9 @@ int enable_pcie_clock(void)
(struct anatop_regs *)ANATOP_BASE_ADDR;
struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ /* PCIe reference clock sourced from AXI. */
+ clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL);
+
/*
* Here be dragons!
*
@@ -773,22 +785,30 @@ int enable_pcie_clock(void)
#define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12)
#define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10)
#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK 0x0000001F
+#ifndef CONFIG_MX6SX
+ /* lvds_clk1 is sourced from sata ref on imx6q/dl/solo */
clrsetbits_le32(&anatop_regs->ana_misc1,
ANADIG_ANA_MISC1_LVDSCLK1_IBEN |
ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK,
ANADIG_ANA_MISC1_LVDSCLK1_OBEN | 0xb);
- /* PCIe reference clock sourced from AXI. */
- clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL);
-
/* Party time! Ungate the clock to the PCIe. */
-#ifndef CONFIG_MX6SX
ungate_sata_clock();
-#endif
ungate_pcie_clock();
return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA |
- BM_ANADIG_PLL_ENET_ENABLE_PCIE);
+ BM_ANADIG_PLL_ENET_ENABLE_PCIE);
+#else
+ /* lvds_clk1 is sourced from pcie ref on imx6sx */
+ clrsetbits_le32(&anatop_regs->ana_misc1,
+ ANADIG_ANA_MISC1_LVDSCLK1_IBEN |
+ ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK,
+ ANADIG_ANA_MISC1_LVDSCLK1_OBEN | 0xa);
+
+ ungate_disp_axi_clock();
+ ungate_pcie_clock();
+ return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_PCIE);
+#endif
}
#ifdef CONFIG_SECURE_BOOT
diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
index e4393b3..fa1d6e6 100644
--- a/arch/arm/cpu/armv7/mx6/soc.c
+++ b/arch/arm/cpu/armv7/mx6/soc.c
@@ -427,6 +427,16 @@ void vadc_power_down(void)
val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK,
writel(val, &iomux->gpr[5]);
}
+
+void pcie_power_up(void)
+{
+ set_ldo_voltage(LDO_PU, 1100); /* Set VDDPU to 1.1V */
+}
+
+void pcie_power_off(void)
+{
+ set_ldo_voltage(LDO_PU, 0); /* Set VDDPU to 1.1V */
+}
#endif
static void imx_set_vddpu_power_down(void)
diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h
index 1692866..fad04f6 100644
--- a/arch/arm/include/asm/arch-mx6/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx6/imx-regs.h
@@ -1104,6 +1104,8 @@ extern void check_cpu_temperature(void);
#ifdef CONFIG_MX6SX
extern void vadc_power_up(void);
extern void vadc_power_down(void);
+extern void pcie_power_up(void);
+extern void pcie_power_off(void);
#endif
/* If ROM fail back to USB recover mode, USBPH0_PWD will be clear to use USB
diff --git a/arch/arm/include/asm/arch-mx6/iomux.h b/arch/arm/include/asm/arch-mx6/iomux.h
index c3003c1..dba2186 100644
--- a/arch/arm/include/asm/arch-mx6/iomux.h
+++ b/arch/arm/include/asm/arch-mx6/iomux.h
@@ -19,6 +19,12 @@
#define IOMUXC_GPR1_TEST_POWERDOWN (1 << 18)
/*
+ * IOMUXC_GPR5 bit fields
+ */
+#define IOMUXC_GPR5_PCIE_BTNRST (1 << 19)
+#define IOMUXC_GPR5_PCIE_PERST (1 << 18)
+
+/*
* IOMUXC_GPR8 bit fields
*/
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_MASK (0x3f << 0)
@@ -35,12 +41,15 @@
/*
* IOMUXC_GPR12 bit fields
*/
+#define IOMUXC_GPR12_RX_EQ_2 (0x2 << 0)
+#define IOMUXC_GPR12_RX_EQ_MASK (0x7 << 0)
#define IOMUXC_GPR12_LOS_LEVEL_9 (0x9 << 4)
#define IOMUXC_GPR12_LOS_LEVEL_MASK (0x1f << 4)
#define IOMUXC_GPR12_APPS_LTSSM_ENABLE (1 << 10)
#define IOMUXC_GPR12_DEVICE_TYPE_EP (0x0 << 12)
-#define IOMUXC_GPR12_DEVICE_TYPE_RC (0x2 << 12)
+#define IOMUXC_GPR12_DEVICE_TYPE_RC (0x4 << 12)
#define IOMUXC_GPR12_DEVICE_TYPE_MASK (0xf << 12)
+#define IOMUXC_GPR12_TEST_POWERDOWN (1 << 30)
/*
* IOMUXC_GPR13 bit fields
diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c
index c48737e..0b5b886 100644
--- a/drivers/pci/pcie_imx.c
+++ b/drivers/pci/pcie_imx.c
@@ -23,13 +23,20 @@
#define PCI_ACCESS_READ 0
#define PCI_ACCESS_WRITE 1
+#ifdef CONFIG_MX6SX
+#define MX6_DBI_ADDR 0x08ffc000
+#define MX6_IO_ADDR 0x08000000
+#define MX6_MEM_ADDR 0x08100000
+#define MX6_ROOT_ADDR 0x08f00000
+#else
#define MX6_DBI_ADDR 0x01ffc000
-#define MX6_DBI_SIZE 0x4000
#define MX6_IO_ADDR 0x01000000
-#define MX6_IO_SIZE 0x100000
#define MX6_MEM_ADDR 0x01100000
-#define MX6_MEM_SIZE 0xe00000
#define MX6_ROOT_ADDR 0x01f00000
+#endif
+#define MX6_DBI_SIZE 0x4000
+#define MX6_IO_SIZE 0x100000
+#define MX6_MEM_SIZE 0xe00000
#define MX6_ROOT_SIZE 0xfc000
/* PCIe Port Logic registers (memory-mapped) */
@@ -80,6 +87,46 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
+#ifdef DEBUG
+
+#ifdef DEBUG_STRESS_WR /* warm-reset stress tests */
+#define SNVS_LPGRP 0x020cc068
+#endif
+
+#define DBGF(x...) printf(x)
+
+static void print_regs(int contain_pcie_reg)
+{
+ u32 val;
+#ifndef CONFIG_MX6SX
+ struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+#else
+ struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR;
+#endif
+ val = readl(&iomuxc_regs->gpr[1]);
+ DBGF("GPR01 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[1], val);
+ val = readl(&iomuxc_regs->gpr[5]);
+ DBGF("GPR05 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[5], val);
+ val = readl(&iomuxc_regs->gpr[8]);
+ DBGF("GPR08 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[8], val);
+ val = readl(&iomuxc_regs->gpr[12]);
+ DBGF("GPR12 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[12], val);
+ val = readl(ANATOP_BASE_ADDR + 0xe0);
+ DBGF("PLL06 a:0x%08x v:0x%08x\n", ANATOP_BASE_ADDR + 0xe0, val);
+ val = readl(ANATOP_BASE_ADDR + 0x160);
+ DBGF("MISC1 a:0x%08x v:0x%08x\n", ANATOP_BASE_ADDR + 0x160, val);
+ if (contain_pcie_reg) {
+ val = readl(MX6_DBI_ADDR + 0x728);
+ DBGF("dbr0 offset 0x728 %08x\n", val);
+ val = readl(MX6_DBI_ADDR + 0x72c);
+ DBGF("dbr1 offset 0x72c %08x\n", val);
+ }
+}
+#else
+#define DBGF(x...)
+static void print_regs(int contain_pcie_reg) {}
+#endif
+
/*
* PHY access functions
*/
@@ -420,19 +467,43 @@ static int imx_pcie_write_config(struct pci_controller *hose, pci_dev_t d,
*/
static int imx6_pcie_assert_core_reset(void)
{
+#ifndef CONFIG_MX6SX
struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+#else
+ u32 val;
+ struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR;
+#endif
+#if defined(CONFIG_MX6SX)
+ /* SSP_EN is not used on iMX6SX anymore */
+ setbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_TEST_POWERDOWN);
+ /* Force PCIe PHY reset */
+ setbits_le32(&iomuxc_regs->gpr[5], IOMUXC_GPR5_PCIE_BTNRST);
+
+ /* Power up PCIe PHY, ANATOP_REG_CORE offset 0x140, bit13-9 */
+ val = readl(GPC_BASE_ADDR + 0);
+ val |= (0x1 << 7);
+ writel(val, GPC_BASE_ADDR + 0);
+ pcie_power_up();
+#else
setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN);
clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN);
+#endif
return 0;
}
static int imx6_pcie_init_phy(void)
{
+#ifndef CONFIG_MX6SX
struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+#else
+ struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR;
+#endif
+#ifndef DEBUG
clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_APPS_LTSSM_ENABLE);
+#endif
clrsetbits_le32(&iomuxc_regs->gpr[12],
IOMUXC_GPR12_DEVICE_TYPE_MASK,
@@ -440,6 +511,11 @@ static int imx6_pcie_init_phy(void)
clrsetbits_le32(&iomuxc_regs->gpr[12],
IOMUXC_GPR12_LOS_LEVEL_MASK,
IOMUXC_GPR12_LOS_LEVEL_9);
+#ifdef CONFIG_MX6SX
+ clrsetbits_le32(&iomuxc_regs->gpr[12],
+ IOMUXC_GPR12_RX_EQ_MASK,
+ IOMUXC_GPR12_RX_EQ_2);
+#endif
writel((0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_OFFSET) |
(0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_OFFSET) |
@@ -505,21 +581,38 @@ __weak int imx6_pcie_toggle_reset(void)
static int imx6_pcie_deassert_core_reset(void)
{
+#ifndef CONFIG_MX6SX
struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+#else
+ struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR;
+#endif
imx6_pcie_toggle_power();
+ enable_pcie_clock();
+
/* Enable PCIe */
+#if defined(CONFIG_MX6SX)
+ /* SSP_EN is not used on iMX6SX anymore */
+ clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_TEST_POWERDOWN);
+ /*
+ * iMX6SX PCIe has the stand-alone power domain.
+ * refer to the initialization for iMX6SX PCIe,
+ * release the PCIe PHY reset here,
+ * before LTSSM enable is set
+ * .
+ */
+ clrbits_le32(&iomuxc_regs->gpr[5], IOMUXC_GPR5_PCIE_BTNRST);
+#else
clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN);
setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN);
- enable_pcie_clock();
-
/*
* Wait for the clock to settle a bit, when the clock are sourced
* from the CPU, we need about 30mS to settle.
*/
mdelay(50);
+#endif
imx6_pcie_toggle_reset();
@@ -528,7 +621,11 @@ static int imx6_pcie_deassert_core_reset(void)
static int imx_pcie_link_up(void)
{
+#ifndef CONFIG_MX6SX
struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+#else
+ struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR;
+#endif
uint32_t tmp;
int count = 0;
@@ -555,9 +652,25 @@ static int imx_pcie_link_up(void)
while (!imx6_pcie_link_up()) {
udelay(10);
count++;
+ if (count == 1000) {
+ print_regs(1);
+ /* link down, try reset ep, and re-try link here */
+ DBGF("pcie link is down, reset ep, then retry!\n");
+ imx6_pcie_toggle_reset();
+ continue;
+ }
+#ifdef DEBUG
+ else if (count >= 2000) {
+ print_regs(1);
+ /* link is down, stop here */
+ setenv("bootcmd", "sleep 2;");
+ DBGF("pcie link is down, stop here!\n");
+ return -EINVAL;
+ }
+#endif
if (count >= 2000) {
- debug("phy link never came up\n");
- debug("DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
+ printf("phy link never came up\n");
+ printf("DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
readl(MX6_DBI_ADDR + PCIE_PHY_DEBUG_R0),
readl(MX6_DBI_ADDR + PCIE_PHY_DEBUG_R1));
return -EINVAL;
@@ -573,6 +686,10 @@ void imx_pcie_init(void)
static struct pci_controller pcc;
struct pci_controller *hose = &pcc;
int ret;
+#ifdef DEBUG_STRESS_WR
+ u32 dbg_reg_addr = SNVS_LPGRP;
+ u32 dbg_reg = readl(dbg_reg_addr) + 1;
+#endif
memset(&pcc, 0, sizeof(pcc));
@@ -607,7 +724,15 @@ void imx_pcie_init(void)
if (!ret) {
pci_register_hose(hose);
hose->last_busno = pci_hose_scan(hose);
+#ifdef DEBUG_STRESS_WR
+ dbg_reg += 1<<16;
+#endif
}
+#ifdef DEBUG_STRESS_WR
+ writel(dbg_reg, dbg_reg_addr);
+ DBGF("PCIe Successes/Attempts: %d/%d\n",
+ dbg_reg >> 16, dbg_reg & 0xffff);
+#endif
}
/* Probe function. */
diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h
index 97c5a5b..96a81c0 100644
--- a/include/configs/mx6sxsabresd.h
+++ b/include/configs/mx6sxsabresd.h
@@ -367,6 +367,16 @@
#define CONFIG_MXC_USB_FLAGS 0
#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
+#define CONFIG_CMD_PCI
+#ifdef CONFIG_CMD_PCI
+#define CONFIG_PCI
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#define CONFIG_PCIE_IMX
+#define CONFIG_PCIE_IMX_PERST_GPIO IMX_GPIO_NR(2, 1)
+#define CONFIG_PCIE_IMX_POWER_GPIO IMX_GPIO_NR(2, 0)
+#endif
+
#if defined(CONFIG_ANDROID_SUPPORT)
#include "mx6sxsabresdandroid.h"
#endif