Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix case when system is shut down without reinitializing the pci #8

Open
wants to merge 1 commit into
base: imx6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 66 additions & 9 deletions arch/arm/cpu/armv7/mx6/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,18 +405,14 @@ u32 imx_get_fecclk(void)
return mxc_get_clock(MXC_IPG_CLK);
}

int enable_sata_clock(void)
static int enable_enet_pll(uint32_t en)
{
u32 reg = 0;
s32 timeout = 100000;
s32 timeout = 100000;
u32 reg = 0;

struct mxc_ccm_reg *const imx_ccm
= (struct mxc_ccm_reg *) CCM_BASE_ADDR;

/* Enable sata clock */
reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
reg |= MXC_CCM_CCGR5_SATA_MASK;
writel(reg, &imx_ccm->CCGR5);

/* Enable PLLs */
reg = readl(&imx_ccm->analog_pll_enet);
reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN;
Expand All @@ -430,12 +426,73 @@ int enable_sata_clock(void)
return -EIO;
reg &= ~BM_ANADIG_PLL_SYS_BYPASS;
writel(reg, &imx_ccm->analog_pll_enet);
reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
reg |= en;
writel(reg, &imx_ccm->analog_pll_enet);

return 0 ;
}

static void ungate_sata_clock(void)
{
struct mxc_ccm_reg *const imx_ccm =
(struct mxc_ccm_reg *)CCM_BASE_ADDR;

/* Enable SATA clock. */
setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
}

static void ungate_pcie_clock(void)
{
struct mxc_ccm_reg *const imx_ccm =
(struct mxc_ccm_reg *)CCM_BASE_ADDR;

/* Enable PCIe clock. */
setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_PCIE_MASK);
}

int enable_sata_clock(void)
{
ungate_sata_clock();
return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA);
}

int enable_pcie_clock(void)
{
struct anatop_regs *anatop_regs =
(struct anatop_regs *)ANATOP_BASE_ADDR;
struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;

/*
* Here be dragons!
*
* The register ANATOP_MISC1 is not documented in the Freescale
* MX6RM. The register that is mapped in the ANATOP space and
* marked as ANATOP_MISC1 is actually documented in the PMU section
* of the datasheet as PMU_MISC1.
*
* Switch LVDS clock source to SATA (0xb), disable clock INPUT and
* enable clock OUTPUT. This is important for PCI express link that
* is clocked from the i.MX6.
*/
#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
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. */
ungate_sata_clock();
ungate_pcie_clock();

return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA |
BM_ANADIG_PLL_ENET_ENABLE_PCIE);
}

unsigned int mxc_get_clock(enum mxc_clock clk)
{
switch (clk) {
Expand Down
1 change: 1 addition & 0 deletions arch/arm/include/asm/arch-mx6/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ unsigned int mxc_get_clock(enum mxc_clock clk);
void enable_ocotp_clk(unsigned char enable);
void enable_usboh3_clk(unsigned char enable);
int enable_sata_clock(void);
int enable_pcie_clock(void);
int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
void enable_ipu_clock(void);
int enable_fec_anatop_clock(void);
Expand Down
31 changes: 31 additions & 0 deletions arch/arm/include/asm/arch-mx6/iomux.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,34 @@
|IOMUXC_GPR13_SATA_PHY_2_MASK \
|IOMUXC_GPR13_SATA_PHY_1_MASK)
#endif /* __ASM_ARCH_IOMUX_H__ */

/*
* For pcie reset patch
*/

#define IOMUXC_GPR1_REF_SSP_EN (1 << 16)
#define IOMUXC_GPR1_TEST_POWERDOWN (1 << 18)

/*
* IOMUXC_GPR12 bit fields
*/
#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_MASK (0xf << 12)

/*
* IOMUXC_GPR8 bit fields
*/
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_MASK (0x3f << 0)
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_OFFSET 0
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_MASK (0x3f << 6)
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_OFFSET 6
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_6DB_MASK (0x3f << 12)
#define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_6DB_OFFSET 12
#define IOMUXC_GPR8_PCS_TX_SWING_FULL_MASK (0x7f << 18)
#define IOMUXC_GPR8_PCS_TX_SWING_FULL_OFFSET 18
#define IOMUXC_GPR8_PCS_TX_SWING_LOW_MASK (0x7f << 25)
#define IOMUXC_GPR8_PCS_TX_SWING_LOW_OFFSET 25
8 changes: 8 additions & 0 deletions board/solidrun/mx6_cubox-i/mx6_cubox-i.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,14 @@ int setup_sata(void)
}
#endif

/* PCI Probe function. */
void pci_init_board(void)
{
/* At this point we only support reset. This is to solve the reboot hang problem due to wrong pcie status */
imx_pcie_reset();
}


int board_init(void)
{
/* address of boot parameters */
Expand Down
1 change: 1 addition & 0 deletions drivers/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ COBJS-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o
COBJS-$(CONFIG_PCI) += pci.o pci_auto.o
COBJS-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
COBJS-$(CONFIG_PCI_GT64120) += pci_gt64120.o
COBJS-$(CONFIG_PCIE_IMX) += pcie_imx.o
COBJS-$(CONFIG_FTPCI100) += pci_ftpci100.o
COBJS-$(CONFIG_IXP_PCI) += pci_ixp.o
COBJS-$(CONFIG_SH4_PCI) += pci_sh4.o
Expand Down
Loading