aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2008-02-23 16:08:27 -0500
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2008-03-26 08:19:16 -0400
commit66b7e504c0e66c568b1759882884b8e1cfb307bd (patch)
tree5399619ba1de5c865fce5b5ad02c591d7f70ce18 /arch/powerpc/sysdev
parent8bc4a51d28b760b40b21217c7d613777cfeeb3b0 (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.c114
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.h59
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
779static int __init ppc460ex_pciex_core_init(struct device_node *np)
780{
781 /* Nothing to do, return 2 ports */
782 return 2;
783}
784
785static 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
863static 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
883static 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
357enum 416enum
358{ 417{