diff options
-rw-r--r-- | arch/arm/cpu/armv7/mx6/clock.c | 32 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx6/soc.c | 10 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/imx-regs.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/iomux.h | 11 | ||||
-rw-r--r-- | drivers/pci/pcie_imx.c | 139 | ||||
-rw-r--r-- | include/configs/mx6sxsabresd.h | 10 |
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 |