[PATCH] powerpc: p1022: add two functions for reset pci slot
From: Dongsheng Wang <hidden>
Date: 2016-01-22 08:43:29
From: Wang Dongsheng <redacted> When the DIU enable, only through the way of indirect access to read/write pixis register. So add direct and indirect for pci slot reset. Signed-off-by: Wang Dongsheng <redacted>
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 371df82..5c8894c 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c@@ -53,23 +53,6 @@ #define CLKDVDR_PXCKDLY 0x06000000 #define CLKDVDR_PXCLK_MASK 0x00FF0000 -/* Some ngPIXIS register definitions */ -#define PX_CTL 3 -#define PX_BRDCFG0 8 -#define PX_BRDCFG1 9 - -#define PX_BRDCFG0_ELBC_SPI_MASK 0xc0 -#define PX_BRDCFG0_ELBC_SPI_ELBC 0x00 -#define PX_BRDCFG0_ELBC_SPI_NULL 0xc0 -#define PX_BRDCFG0_ELBC_DIU 0x02 - -#define PX_BRDCFG1_DVIEN 0x80 -#define PX_BRDCFG1_DFPEN 0x40 -#define PX_BRDCFG1_BACKLIGHT 0x20 -#define PX_BRDCFG1_DDCEN 0x10 - -#define PX_CTL_ALTACC 0x80 - /* * DIU Area Descriptor *
@@ -106,6 +89,28 @@ (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \ (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT)) +#endif + +/* Some ngPIXIS register definitions */ +#define PX_CTL 3 +#define PX_BRDCFG0 8 +#define PX_BRDCFG1 9 + +#define PX_RST 0x4 +#define PX_RST_PCIE 0x8 + +#define PX_BRDCFG0_ELBC_SPI_MASK 0xc0 +#define PX_BRDCFG0_ELBC_SPI_ELBC 0x00 +#define PX_BRDCFG0_ELBC_SPI_NULL 0xc0 +#define PX_BRDCFG0_ELBC_DIU 0x02 + +#define PX_BRDCFG1_DVIEN 0x80 +#define PX_BRDCFG1_DFPEN 0x40 +#define PX_BRDCFG1_BACKLIGHT 0x20 +#define PX_BRDCFG1_DDCEN 0x10 + +#define PX_CTL_ALTACC 0x80 + struct fsl_law { u32 lawbar; u32 reserved1;
@@ -125,6 +130,8 @@ struct fsl_law { #define BR_BA 0xFFFF8000 +static int px_ctl_altacc_flag; + /* * Map a BRx value to a physical address *
@@ -157,48 +164,40 @@ static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br) #endif } -/** - * p1022ds_set_monitor_port: switch the output to a different monitor port - */ -static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) +static u8 __iomem *lbc_lcs0_ba; +static u8 __iomem *lbc_lcs1_ba; + +static inline bool verify_pixis_indirect_access_address(void) { - struct device_node *guts_node; - struct device_node *lbc_node = NULL; - struct device_node *law_node = NULL; - struct ccsr_guts __iomem *guts; - struct fsl_lbc_regs *lbc = NULL; + if (lbc_lcs0_ba && lbc_lcs1_ba) + return true; + + return false; +} + +static void indirect_access_pixis_probe(void) +{ + struct device_node *lbc_node; + struct device_node *law_node; + struct fsl_lbc_regs *lbc; void *ecm = NULL; - u8 __iomem *lbc_lcs0_ba = NULL; - u8 __iomem *lbc_lcs1_ba = NULL; + phys_addr_t cs0_addr, cs1_addr; u32 br0, or0, br1, or1; const __be32 *iprop; unsigned int num_laws; - u8 b; - - /* Map the global utilities registers. */ - guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); - if (!guts_node) { - pr_err("p1022ds: missing global utilities device node\n"); - return; - } - - guts = of_iomap(guts_node, 0); - if (!guts) { - pr_err("p1022ds: could not map global utilities device\n"); - goto exit; - } lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); if (!lbc_node) { pr_err("p1022ds: missing localbus node\n"); - goto exit; + return; } lbc = of_iomap(lbc_node, 0); + of_node_put(lbc_node); if (!lbc) { pr_err("p1022ds: could not map localbus node\n"); - goto exit; + return; } law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
@@ -282,7 +281,103 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) if (!lbc_lcs1_ba) { pr_err("p1022ds: could not ioremap CS1 address %llx\n", (unsigned long long)cs1_addr); - goto exit; + + iounmap(lbc_lcs0_ba); + } + +exit: + if (ecm) + iounmap(ecm); + if (lbc) + iounmap(lbc); + + if (law_node) + of_node_put(law_node); +} + +static void indirect_access_pixis_reset_pcie_slot(void) +{ + if (!verify_pixis_indirect_access_address()) { + WARN_ON(1); + return; + } + + /* Set FPGA access address */ + out_8(lbc_lcs0_ba, PX_RST); + + /* power down pcie slot */ + clrbits8(lbc_lcs1_ba, PX_RST_PCIE); + + /* power up pcie slot */ + setbits8(lbc_lcs1_ba, PX_RST_PCIE); +} + +static void direct_access_pixis_reset_pcie_slot(void) +{ + struct device_node *pixis_node; + void __iomem *pixis; + + /* Map the pixis registers. */ + pixis_node = + of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); + if (!pixis_node) { + pr_err("p1022ds: missing pixis node\n"); + return; + } + + pixis = of_iomap(pixis_node, 0); + of_node_put(pixis_node); + if (!pixis) { + pr_err("p1022ds: could not map pixis registers\n"); + return; + } + + /* Rset PCIE slot */ + /* power down pcie slot */ + clrbits8(pixis + PX_RST, PX_RST_PCIE); + + /* power up pcie slot */ + setbits8(pixis + PX_RST, PX_RST_PCIE); + + iounmap(pixis); +} + +void p1022ds_reset_pcie_slot(void) +{ + if (px_ctl_altacc_flag) + indirect_access_pixis_reset_pcie_slot(); + else + direct_access_pixis_reset_pcie_slot(); +} + +#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) + +/** + * p1022ds_set_monitor_port: switch the output to a different monitor port + */ +static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) +{ + struct device_node *guts_node; + struct ccsr_guts __iomem *guts; + u8 b; + + if (!verify_pixis_indirect_access_address()) { + WARN_ON(1); + return; + } + + /* Map the global utilities registers. */ + guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); + if (!guts_node) { + pr_err("p1022ds: missing global utilities device node\n"); + return; + } + + guts = of_iomap(guts_node, 0); + of_node_put(guts_node); + if (!guts) { + pr_err("p1022ds: could not map global utilities device\n"); + return; } /* Make sure we're in indirect mode first. */
@@ -307,6 +402,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) /* Enable indirect PIXIS mode. */ setbits8(pixis + PX_CTL, PX_CTL_ALTACC); + px_ctl_altacc_flag = 1; iounmap(pixis); /* Switch the board mux to the DIU */
@@ -348,20 +444,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) } exit: - if (lbc_lcs1_ba) - iounmap(lbc_lcs1_ba); - if (lbc_lcs0_ba) - iounmap(lbc_lcs0_ba); - if (lbc) - iounmap(lbc); - if (ecm) - iounmap(ecm); - if (guts) - iounmap(guts); - - of_node_put(law_node); - of_node_put(lbc_node); - of_node_put(guts_node); + iounmap(guts); } /**
@@ -543,6 +626,8 @@ static void __init p1022_ds_setup_arch(void) swiotlb_detect_4g(); + indirect_access_pixis_probe(); + pr_info("Freescale P1022 DS reference board\n"); }
--
2.1.0.27.g96db324