diff options
author | Ye Li <ye.li@nxp.com> | 2016-03-11 17:28:00 +0800 |
---|---|---|
committer | Ye Li <ye.li@nxp.com> | 2016-03-25 16:04:31 +0800 |
commit | 81fd30250110d72992758f08b66c07306126892b (patch) | |
tree | f84ceffd8d36fd67f8ae107e8a2270cffc5107e0 | |
parent | 48a4606ef575c72e16e31c167dce042fcb66191c (diff) | |
download | u-boot-imx-81fd30250110d72992758f08b66c07306126892b.zip u-boot-imx-81fd30250110d72992758f08b66c07306126892b.tar.gz u-boot-imx-81fd30250110d72992758f08b66c07306126892b.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.
(cherry picked from commit ec78595a24b5ff1020baa97b6d6e79a3a3326307)
Signed-off-by: Richard Zhu <r65037@freescale.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
-rw-r--r-- | arch/arm/cpu/armv7/mx6/clock.c | 27 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx6/soc.c | 10 | ||||
-rw-r--r-- | arch/arm/include/asm/imx-common/sys_proto.h | 3 | ||||
-rw-r--r-- | drivers/pci/pcie_imx.c | 72 |
4 files changed, 106 insertions, 6 deletions
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index b760fec..89f097b 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -1094,6 +1094,15 @@ void disable_sata_clock(void) #endif #ifdef CONFIG_PCIE_IMX +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); +} + static void ungate_pcie_clock(void) { struct mxc_ccm_reg *const imx_ccm = @@ -1141,14 +1150,22 @@ int enable_pcie_clock(void) /* 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. */ + if (!is_cpu_type(MXC_CPU_MX6SX)) { + /* Party time! Ungate the clock to the PCIe. */ #ifdef CONFIG_CMD_SATA - ungate_sata_clock(); + ungate_sata_clock(); #endif - ungate_pcie_clock(); + ungate_pcie_clock(); - return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA | - BM_ANADIG_PLL_ENET_ENABLE_PCIE); + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA | + BM_ANADIG_PLL_ENET_ENABLE_PCIE); + } else { + /* Party time! Ungate the clock to the PCIe. */ + ungate_disp_axi_clock(); + ungate_pcie_clock(); + + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_PCIE); + } } #endif diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index c8bb203..e5d1a86 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -365,6 +365,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 set_uart_from_osc(void) diff --git a/arch/arm/include/asm/imx-common/sys_proto.h b/arch/arm/include/asm/imx-common/sys_proto.h index 93d0b20..fdaac3f 100644 --- a/arch/arm/include/asm/imx-common/sys_proto.h +++ b/arch/arm/include/asm/imx-common/sys_proto.h @@ -61,6 +61,9 @@ void board_late_mmc_env_init(void); void vadc_power_up(void); void vadc_power_down(void); +void pcie_power_up(void); +void pcie_power_off(void); + int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data); int arch_auxiliary_core_check_up(u32 core_id); #endif diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c index c14bb0a..28d10c3 100644 --- a/drivers/pci/pcie_imx.c +++ b/drivers/pci/pcie_imx.c @@ -3,6 +3,8 @@ * * Copyright (C) 2013 Marek Vasut <marex@denx.de> * + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. + * * Based on upstream Linux kernel driver: * pci-imx6.c: Sean Cross <xobs@kosagi.com> * pcie-designware.c: Jingoo Han <jg1.han@samsung.com> @@ -90,6 +92,43 @@ #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; + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; + struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + 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(&ccm_regs->analog_pll_enet); + DBGF("PLL06 a:0x%08x v:0x%08x\n", (u32)&ccm_regs->analog_pll_enet, val); + val = readl(&ccm_regs->ana_misc1); + DBGF("MISC1 a:0x%08x v:0x%08x\n", (u32)&ccm_regs->ana_misc1, 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 */ @@ -381,7 +420,7 @@ static int imx_pcie_read_config(struct pci_controller *hose, pci_dev_t d, ret = imx_pcie_addr_valid(d); if (ret) { *val = 0xffffffff; - return 0; + return ret; } va_address = get_bus_address(d, where); @@ -444,6 +483,7 @@ static int imx6_pcie_assert_core_reset(void) setbits_le32(&iomuxc_regs->gpr[5], IOMUXC_GPR5_PCIE_BTNRST); /* Power up PCIe PHY */ setbits_le32(&gpc_regs->cntr, PCIE_PHY_PUP_REQ); + 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); @@ -456,7 +496,9 @@ static int imx6_pcie_init_phy(void) { struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; +#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, @@ -595,6 +637,22 @@ 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) { #ifdef CONFIG_PCI_SCAN_SHOW puts("PCI: pcie phy link never came up\n"); @@ -615,6 +673,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)); @@ -649,7 +711,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. */ |