4xx_pcie.c
来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 1,172 行 · 第 1/3 页
C
1,172 行
time_out--; udelay(1); } else break; } if (!time_out) { printf("PCIE: VCO output not locked\n"); return -1; } return 0;}#endif#if defined(CONFIG_460EX) || defined(CONFIG_460GT)static void ppc4xx_setup_utl(u32 port){ volatile void *utl_base = NULL; /* * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK */ switch (port) { case 0: mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE)); mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE)); mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* BAM 11100000=4KB */ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0); break; case 1: mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE)); mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE) + 0x1000); mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* BAM 11100000=4KB */ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0); break; } utl_base = (unsigned int *)(CFG_PCIE_BASE + 0x1000 * port); /* * Set buffer allocations and then assert VRB and TXE. */ out_be32(utl_base + PEUTL_PBCTL, 0x0800000c); /* PLBME, CRRE */ out_be32(utl_base + PEUTL_OUTTR, 0x08000000); out_be32(utl_base + PEUTL_INTR, 0x02000000); out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000); /* OPD = 512 Bytes */ out_be32(utl_base + PEUTL_PBBSZ, 0x00000000); /* Max 512 Bytes */ out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000); out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000); /* IPD = 512 Bytes */ out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); out_be32(utl_base + PEUTL_PCTL, 0x80800066); /* VRB,TXE,timeout=default */}/* * TODO: double check PCI express SDR based on the latest user manual * Some registers specified here no longer exist.. has to be * updated based on the final EAS spec. */static int check_error(void){ u32 valPE0, valPE1; int err = 0; valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0)); valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1)); /* SDR0_PExRCSSET rstgu */ if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) { printf("PCIE: SDR0_PExRCSSET rstgu error\n"); err = -1; } /* SDR0_PExRCSSET rstdl */ if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) { printf("PCIE: SDR0_PExRCSSET rstdl error\n"); err = -1; } /* SDR0_PExRCSSET rstpyn */ if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) { printf("PCIE: SDR0_PExRCSSET rstpyn error\n"); err = -1; } /* SDR0_PExRCSSET hldplb */ if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) { printf("PCIE: SDR0_PExRCSSET hldplb error\n"); err = -1; } /* SDR0_PExRCSSET rdy */ if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) { printf("PCIE: SDR0_PExRCSSET rdy error\n"); err = -1; } return err;}/* * Initialize PCI Express core as described in User Manual * TODO: double check PE SDR PLL Register with the updated user manual. */int ppc4xx_init_pcie(void){ if (check_error()) return -1; return 0;}#endif /* CONFIG_460EX */#if defined(CONFIG_405EX)static void ppc4xx_setup_utl(u32 port){ u32 utl_base; /* * Map UTL registers at 0xef4f_n000 (4K 0xfff mask) PEGPLn_REGMSK */ switch (port) { case 0: mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x00000000); mtdcr(DCRN_PEGPL_REGBAL(PCIE0), CFG_PCIE0_UTLBASE); mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* 4k region, valid */ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0); break; case 1: mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x00000000); mtdcr(DCRN_PEGPL_REGBAL(PCIE1), CFG_PCIE1_UTLBASE); mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* 4k region, valid */ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0); break; } utl_base = (port==0) ? CFG_PCIE0_UTLBASE : CFG_PCIE1_UTLBASE; /* * Set buffer allocations and then assert VRB and TXE. */ out_be32((u32 *)(utl_base + PEUTL_OUTTR), 0x02000000); out_be32((u32 *)(utl_base + PEUTL_INTR), 0x02000000); out_be32((u32 *)(utl_base + PEUTL_OPDBSZ), 0x04000000); out_be32((u32 *)(utl_base + PEUTL_PBBSZ), 0x21000000); out_be32((u32 *)(utl_base + PEUTL_IPHBSZ), 0x02000000); out_be32((u32 *)(utl_base + PEUTL_IPDBSZ), 0x04000000); out_be32((u32 *)(utl_base + PEUTL_RCIRQEN), 0x00f00000); out_be32((u32 *)(utl_base + PEUTL_PCTL), 0x80800066); out_be32((u32 *)(utl_base + PEUTL_PBCTL), 0x0800000c); out_be32((u32 *)(utl_base + PEUTL_RCSTA), in_be32((u32 *)(utl_base + PEUTL_RCSTA)) | 0x000040000);}int ppc4xx_init_pcie(void){ /* * Nothing to do on 405EX */ return 0;}#endif /* CONFIG_405EX *//* * Board-specific pcie initialization * Platform code can reimplement ppc4xx_init_pcie_port_hw() if needed *//* * Initialize various parts of the PCI Express core for our port: * * - Set as a root port and enable max width * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). * - Set up UTL configuration. * - Increase SERDES drive strength to levels suggested by AMCC. * - De-assert RSTPYN, RSTDL and RSTGU. * * NOTICE for 440SPE revB chip: PESDRn_UTLSET2 is not set - we leave it * with default setting 0x11310000. The register has new fields, * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core * hang. */#if defined(CONFIG_440SPE)int __ppc4xx_init_pcie_port_hw(int port, int rootport){ u32 val = 1 << 24; u32 utlset1; if (rootport) { val = PTYPE_ROOT_PORT << 20; utlset1 = 0x21222222; } else { val = PTYPE_LEGACY_ENDPOINT << 20; utlset1 = 0x20222222; } if (port == 0) val |= LNKW_X8 << 12; else val |= LNKW_X4 << 12; SDR_WRITE(SDRN_PESDR_DLPSET(port), val); SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1); if (!ppc440spe_revB()) SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x11000000); SDR_WRITE(SDRN_PESDR_HSSL0SET1(port), 0x35000000); SDR_WRITE(SDRN_PESDR_HSSL1SET1(port), 0x35000000); SDR_WRITE(SDRN_PESDR_HSSL2SET1(port), 0x35000000); SDR_WRITE(SDRN_PESDR_HSSL3SET1(port), 0x35000000); if (port == 0) { SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); } SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) & ~(1 << 24 | 1 << 16)) | 1 << 12); return 0;}#endif /* CONFIG_440SPE */#if defined(CONFIG_460EX) || defined(CONFIG_460GT)int __ppc4xx_init_pcie_port_hw(int port, int rootport){ u32 val; u32 utlset1; if (rootport) val = PTYPE_ROOT_PORT << 20; else val = PTYPE_LEGACY_ENDPOINT << 20; if (port == 0) { val |= LNKW_X1 << 12; utlset1 = 0x20000000; } else { val |= LNKW_X4 << 12; utlset1 = 0x20101101; } SDR_WRITE(SDRN_PESDR_DLPSET(port), val); SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1); SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000); switch (port) { case 0: SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230); SDR_WRITE(PESDR0_L0DRV, 0x00000130); SDR_WRITE(PESDR0_L0CLK, 0x00000006); SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000); break; case 1: SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230); SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230); SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230); SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230); SDR_WRITE(PESDR1_L0DRV, 0x00000130); SDR_WRITE(PESDR1_L1DRV, 0x00000130); SDR_WRITE(PESDR1_L2DRV, 0x00000130); SDR_WRITE(PESDR1_L3DRV, 0x00000130); SDR_WRITE(PESDR1_L0CLK, 0x00000006); SDR_WRITE(PESDR1_L1CLK, 0x00000006); SDR_WRITE(PESDR1_L2CLK, 0x00000006); SDR_WRITE(PESDR1_L3CLK, 0x00000006); SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000); break; } SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) | (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN)); /* Poll for PHY reset */ switch (port) { case 0: while (!(SDR_READ(PESDR0_RSTSTA) & 0x1)) udelay(10); break; case 1: while (!(SDR_READ(PESDR1_RSTSTA) & 0x1)) udelay(10); break; } SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) & ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) | PESDRx_RCSSET_RSTPYN); return 0;}#endif /* CONFIG_440SPE */#if defined(CONFIG_405EX)int __ppc4xx_init_pcie_port_hw(int port, int rootport){ u32 val; if (rootport) val = 0x00401000; else val = 0x00101000; SDR_WRITE(SDRN_PESDR_DLPSET(port), val); SDR_WRITE(SDRN_PESDR_UTLSET1(port), 0x00000000); SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01010000); SDR_WRITE(SDRN_PESDR_PHYSET1(port), 0x720F0000); SDR_WRITE(SDRN_PESDR_PHYSET2(port), 0x70600003); /* Assert the PE0_PHY reset */ SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01010000); udelay(1000); /* deassert the PE0_hotreset */ if (is_end_point(port)) SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01111000); else SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01101000); /* poll for phy !reset */ while (!(SDR_READ(SDRN_PESDR_PHYSTA(port)) & 0x00001000)) ; /* deassert the PE0_gpl_utl_reset */ SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x00101000); if (port == 0) mtdcr(DCRN_PEGPL_CFG(PCIE0), 0x10000000); /* guarded on */ else mtdcr(DCRN_PEGPL_CFG(PCIE1), 0x10000000); /* guarded on */ return 0;}#endif /* CONFIG_405EX */int ppc4xx_init_pcie_port_hw(int port, int rootport)__attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));/* * We map PCI Express configuration access into the 512MB regions * * NOTICE: revB is very strict about PLB real addressess and ranges to * be mapped for config space; it seems to only work with d_nnnn_nnnn * range (hangs the core upon config transaction attempts when set * otherwise) while revA uses c_nnnn_nnnn. * * For 440SPe revA: * PCIE0: 0xc_4000_0000 * PCIE1: 0xc_8000_0000 * PCIE2: 0xc_c000_0000 * * For 440SPe revB: * PCIE0: 0xd_0000_0000 * PCIE1: 0xd_2000_0000 * PCIE2: 0xd_4000_0000 * * For 405EX: * PCIE0: 0xa000_0000 * PCIE1: 0xc000_0000 * * For 460EX/GT: * PCIE0: 0xd_0000_0000 * PCIE1: 0xd_2000_0000 */static inline u64 ppc4xx_get_cfgaddr(int port){#if defined(CONFIG_405EX) if (port == 0) return (u64)CFG_PCIE0_CFGBASE; else return (u64)CFG_PCIE1_CFGBASE;#endif#if defined(CONFIG_440SPE) if (ppc440spe_revB()) { switch (port) { default: /* to satisfy compiler */ case 0: return 0x0000000d00000000ULL; case 1: return 0x0000000d20000000ULL; case 2: return 0x0000000d40000000ULL; } } else { switch (port) { default: /* to satisfy compiler */ case 0:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?