diff options
author | Stefan Roese <sr@denx.de> | 2008-02-23 16:08:27 -0500 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2008-03-26 08:19:16 -0400 |
commit | 66b7e504c0e66c568b1759882884b8e1cfb307bd (patch) | |
tree | 5399619ba1de5c865fce5b5ad02c591d7f70ce18 /arch/powerpc/sysdev | |
parent | 8bc4a51d28b760b40b21217c7d613777cfeeb3b0 (diff) |
[POWERPC] 4xx: Add 460EX PCIe support to 4xx pci driver
All this code is needed to properly initialize the 460EX PCIe host
bridge(s). We re-initialize all ports again, even though this has been done
in the bootloader (U-Boot) before. This way we make sure, that we always
run the latest init code in Linux and don't depend on code versions from
U-Boot.
Unfortunately all IBM/AMCC chips currently supported in this PCIe driver need
a different reset-/init-sequence.
Tested on AMCC Canyonlands eval board.
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 114 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.h | 59 |
2 files changed, 173 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 5abfcd157483..d183b8390ec3 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
@@ -527,6 +527,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np) | |||
527 | * | 527 | * |
528 | * ibm,plb-pciex-440spe | 528 | * ibm,plb-pciex-440spe |
529 | * ibm,plb-pciex-405ex | 529 | * ibm,plb-pciex-405ex |
530 | * ibm,plb-pciex-460ex | ||
530 | * | 531 | * |
531 | * Anything else will be rejected for now as they are all subtly | 532 | * Anything else will be rejected for now as they are all subtly |
532 | * different unfortunately. | 533 | * different unfortunately. |
@@ -775,6 +776,117 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = | |||
775 | .setup_utl = ppc440speB_pciex_init_utl, | 776 | .setup_utl = ppc440speB_pciex_init_utl, |
776 | }; | 777 | }; |
777 | 778 | ||
779 | static int __init ppc460ex_pciex_core_init(struct device_node *np) | ||
780 | { | ||
781 | /* Nothing to do, return 2 ports */ | ||
782 | return 2; | ||
783 | } | ||
784 | |||
785 | static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | ||
786 | { | ||
787 | u32 val; | ||
788 | u32 utlset1; | ||
789 | |||
790 | if (port->endpoint) { | ||
791 | val = PTYPE_LEGACY_ENDPOINT << 20; | ||
792 | utlset1 = 0x20222222; | ||
793 | } else { | ||
794 | val = PTYPE_ROOT_PORT << 20; | ||
795 | utlset1 = 0x21222222; | ||
796 | } | ||
797 | |||
798 | if (port->index == 0) { | ||
799 | val |= LNKW_X1 << 12; | ||
800 | } else { | ||
801 | val |= LNKW_X4 << 12; | ||
802 | utlset1 |= 0x00101101; | ||
803 | } | ||
804 | |||
805 | mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val); | ||
806 | mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, utlset1); | ||
807 | mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01210000); | ||
808 | |||
809 | switch (port->index) { | ||
810 | case 0: | ||
811 | mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230); | ||
812 | mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136); | ||
813 | mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006); | ||
814 | |||
815 | mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000); | ||
816 | break; | ||
817 | |||
818 | case 1: | ||
819 | mtdcri(SDR0, PESDR1_460EX_L0CDRCTL, 0x00003230); | ||
820 | mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230); | ||
821 | mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230); | ||
822 | mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230); | ||
823 | mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136); | ||
824 | mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136); | ||
825 | mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136); | ||
826 | mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136); | ||
827 | mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006); | ||
828 | mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006); | ||
829 | mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006); | ||
830 | mtdcri(SDR0, PESDR1_460EX_L3CLK, 0x00000006); | ||
831 | |||
832 | mtdcri(SDR0, PESDR1_460EX_PHY_CTL_RST,0x10000000); | ||
833 | break; | ||
834 | } | ||
835 | |||
836 | mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, | ||
837 | mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | | ||
838 | (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN)); | ||
839 | |||
840 | /* Poll for PHY reset */ | ||
841 | /* XXX FIXME add timeout */ | ||
842 | switch (port->index) { | ||
843 | case 0: | ||
844 | while (!(mfdcri(SDR0, PESDR0_460EX_RSTSTA) & 0x1)) | ||
845 | udelay(10); | ||
846 | break; | ||
847 | case 1: | ||
848 | while (!(mfdcri(SDR0, PESDR1_460EX_RSTSTA) & 0x1)) | ||
849 | udelay(10); | ||
850 | break; | ||
851 | } | ||
852 | |||
853 | mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, | ||
854 | (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) & | ||
855 | ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) | | ||
856 | PESDRx_RCSSET_RSTPYN); | ||
857 | |||
858 | port->has_ibpre = 1; | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) | ||
864 | { | ||
865 | dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0); | ||
866 | |||
867 | /* | ||
868 | * Set buffer allocations and then assert VRB and TXE. | ||
869 | */ | ||
870 | out_be32(port->utl_base + PEUTL_PBCTL, 0x0800000c); | ||
871 | out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000); | ||
872 | out_be32(port->utl_base + PEUTL_INTR, 0x02000000); | ||
873 | out_be32(port->utl_base + PEUTL_OPDBSZ, 0x04000000); | ||
874 | out_be32(port->utl_base + PEUTL_PBBSZ, 0x00000000); | ||
875 | out_be32(port->utl_base + PEUTL_IPHBSZ, 0x02000000); | ||
876 | out_be32(port->utl_base + PEUTL_IPDBSZ, 0x04000000); | ||
877 | out_be32(port->utl_base + PEUTL_RCIRQEN,0x00f00000); | ||
878 | out_be32(port->utl_base + PEUTL_PCTL, 0x80800066); | ||
879 | |||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata = | ||
884 | { | ||
885 | .core_init = ppc460ex_pciex_core_init, | ||
886 | .port_init_hw = ppc460ex_pciex_init_port_hw, | ||
887 | .setup_utl = ppc460ex_pciex_init_utl, | ||
888 | }; | ||
889 | |||
778 | #endif /* CONFIG_44x */ | 890 | #endif /* CONFIG_44x */ |
779 | 891 | ||
780 | #ifdef CONFIG_40x | 892 | #ifdef CONFIG_40x |
@@ -896,6 +1008,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np) | |||
896 | else | 1008 | else |
897 | ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops; | 1009 | ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops; |
898 | } | 1010 | } |
1011 | if (of_device_is_compatible(np, "ibm,plb-pciex-460ex")) | ||
1012 | ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops; | ||
899 | #endif /* CONFIG_44x */ | 1013 | #endif /* CONFIG_44x */ |
900 | #ifdef CONFIG_40x | 1014 | #ifdef CONFIG_40x |
901 | if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) | 1015 | if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) |
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h index 1c07908dc6ef..d04e40b306fb 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.h +++ b/arch/powerpc/sysdev/ppc4xx_pci.h | |||
@@ -271,6 +271,59 @@ | |||
271 | #define PESDR1_405EX_PHYSTA 0x044C | 271 | #define PESDR1_405EX_PHYSTA 0x044C |
272 | 272 | ||
273 | /* | 273 | /* |
274 | * 460EX additional DCRs | ||
275 | */ | ||
276 | #define PESDR0_460EX_L0BIST 0x0308 | ||
277 | #define PESDR0_460EX_L0BISTSTS 0x0309 | ||
278 | #define PESDR0_460EX_L0CDRCTL 0x030A | ||
279 | #define PESDR0_460EX_L0DRV 0x030B | ||
280 | #define PESDR0_460EX_L0REC 0x030C | ||
281 | #define PESDR0_460EX_L0LPB 0x030D | ||
282 | #define PESDR0_460EX_L0CLK 0x030E | ||
283 | #define PESDR0_460EX_PHY_CTL_RST 0x030F | ||
284 | #define PESDR0_460EX_RSTSTA 0x0310 | ||
285 | #define PESDR0_460EX_OBS 0x0311 | ||
286 | #define PESDR0_460EX_L0ERRC 0x0320 | ||
287 | |||
288 | #define PESDR1_460EX_L0BIST 0x0348 | ||
289 | #define PESDR1_460EX_L1BIST 0x0349 | ||
290 | #define PESDR1_460EX_L2BIST 0x034A | ||
291 | #define PESDR1_460EX_L3BIST 0x034B | ||
292 | #define PESDR1_460EX_L0BISTSTS 0x034C | ||
293 | #define PESDR1_460EX_L1BISTSTS 0x034D | ||
294 | #define PESDR1_460EX_L2BISTSTS 0x034E | ||
295 | #define PESDR1_460EX_L3BISTSTS 0x034F | ||
296 | #define PESDR1_460EX_L0CDRCTL 0x0350 | ||
297 | #define PESDR1_460EX_L1CDRCTL 0x0351 | ||
298 | #define PESDR1_460EX_L2CDRCTL 0x0352 | ||
299 | #define PESDR1_460EX_L3CDRCTL 0x0353 | ||
300 | #define PESDR1_460EX_L0DRV 0x0354 | ||
301 | #define PESDR1_460EX_L1DRV 0x0355 | ||
302 | #define PESDR1_460EX_L2DRV 0x0356 | ||
303 | #define PESDR1_460EX_L3DRV 0x0357 | ||
304 | #define PESDR1_460EX_L0REC 0x0358 | ||
305 | #define PESDR1_460EX_L1REC 0x0359 | ||
306 | #define PESDR1_460EX_L2REC 0x035A | ||
307 | #define PESDR1_460EX_L3REC 0x035B | ||
308 | #define PESDR1_460EX_L0LPB 0x035C | ||
309 | #define PESDR1_460EX_L1LPB 0x035D | ||
310 | #define PESDR1_460EX_L2LPB 0x035E | ||
311 | #define PESDR1_460EX_L3LPB 0x035F | ||
312 | #define PESDR1_460EX_L0CLK 0x0360 | ||
313 | #define PESDR1_460EX_L1CLK 0x0361 | ||
314 | #define PESDR1_460EX_L2CLK 0x0362 | ||
315 | #define PESDR1_460EX_L3CLK 0x0363 | ||
316 | #define PESDR1_460EX_PHY_CTL_RST 0x0364 | ||
317 | #define PESDR1_460EX_RSTSTA 0x0365 | ||
318 | #define PESDR1_460EX_OBS 0x0366 | ||
319 | #define PESDR1_460EX_L0ERRC 0x0368 | ||
320 | #define PESDR1_460EX_L1ERRC 0x0369 | ||
321 | #define PESDR1_460EX_L2ERRC 0x036A | ||
322 | #define PESDR1_460EX_L3ERRC 0x036B | ||
323 | #define PESDR0_460EX_IHS1 0x036C | ||
324 | #define PESDR0_460EX_IHS2 0x036D | ||
325 | |||
326 | /* | ||
274 | * Of the above, some are common offsets from the base | 327 | * Of the above, some are common offsets from the base |
275 | */ | 328 | */ |
276 | #define PESDRn_UTLSET1 0x00 | 329 | #define PESDRn_UTLSET1 0x00 |
@@ -353,6 +406,12 @@ | |||
353 | #define PECFG_POM2LAL 0x390 | 406 | #define PECFG_POM2LAL 0x390 |
354 | #define PECFG_POM2LAH 0x394 | 407 | #define PECFG_POM2LAH 0x394 |
355 | 408 | ||
409 | /* SDR Bit Mappings */ | ||
410 | #define PESDRx_RCSSET_HLDPLB 0x10000000 | ||
411 | #define PESDRx_RCSSET_RSTGU 0x01000000 | ||
412 | #define PESDRx_RCSSET_RDY 0x00100000 | ||
413 | #define PESDRx_RCSSET_RSTDL 0x00010000 | ||
414 | #define PESDRx_RCSSET_RSTPYN 0x00001000 | ||
356 | 415 | ||
357 | enum | 416 | enum |
358 | { | 417 | { |