[PATCH] MIPS: OCTEON: Make PCIe work with Little Endian kernel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jia Qingtong <jiaqingtong97@xxxxxxx>

Supply little-endian address bit definitions as well as
set proper endian swapping modes.

Signed-off-by: Jia Qingtong <jiaqingtong97@xxxxxxx>
---
fix pcie setup error when Octeon in little-endian mode

[<ffffffff81bee02c>] octeon_pcie_setup+0x264/0x4e8
[<ffffffff81100514>] do_one_initcall+0x54/0x190
[<ffffffff81bbee7c>] kernel_init_freeable+0x1bc/0x230
[<ffffffff8188b674>] kernel_init+0x10/0x104
[<ffffffff81115350>] ret_from_kernel_thread+0x14/0x1c

 arch/mips/pci/pcie-octeon.c | 85 +++++++++++++++++++++++++++++++------
 1 file changed, 73 insertions(+), 12 deletions(-)

diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c
index d919a0d813a1..512df1e0063a 100644
--- a/arch/mips/pci/pcie-octeon.c
+++ b/arch/mips/pci/pcie-octeon.c
@@ -39,6 +39,7 @@ static int enable_pcie_bus_num_war[2];
 
 union cvmx_pcie_address {
 	uint64_t u64;
+#ifdef __BIG_ENDIAN_BITFIELD
 	struct {
 		uint64_t upper:2;	/* Normally 2 for XKPHYS */
 		uint64_t reserved_49_61:13;	/* Must be zero */
@@ -90,8 +91,68 @@ union cvmx_pcie_address {
 		uint64_t reserved_36_39:4;	/* Must be zero */
 		uint64_t address:36;	/* PCIe Mem address */
 	} mem;
+#else
+	struct {
+		/*
+		 * Selects a register in the configuration space of
+		 * the target.
+		 */
+		uint64_t reg:12;
+		/* Target function number sent in the ID in the request. */
+		uint64_t func:3;
+		/*
+		 * Target device number sent in the ID in the
+		 * request. Note that Dev must be zero for type 0
+		 * configuration requests.
+		 */
+		uint64_t dev:5;
+		/* Target bus number sent in the ID in the request. */
+		uint64_t bus:8;
+		/*
+		 * Selects the type of the configuration request (0 = type 0,
+		 * 1 = type 1).
+		 */
+		uint64_t ty:1;
+		uint64_t reserved_29_31:3;	/* Must be zero */
+		uint64_t port:2;	/* PCIe port 0,1 */
+		uint64_t es:2;	/* Endian swap = 1 */
+		uint64_t reserved_36_39:4;	/* Must be zero */
+		uint64_t subdid:3;	/* PCIe SubDID = 1 */
+		uint64_t did:5; /* PCIe DID = 3 */
+		uint64_t io:1;	/* 1 for IO space access */
+		uint64_t reserved_49_61:13;	/* Must be zero */
+		uint64_t upper:2;	/* Normally 2 for XKPHYS */
+	} config;
+	struct {
+		uint64_t address:32;	/* PCIe IO address */
+		uint64_t port:2;	/* PCIe port 0,1 */
+		uint64_t es:2;	/* Endian swap = 1 */
+		uint64_t reserved_36_39:4;	/* Must be zero */
+		uint64_t subdid:3;	/* PCIe SubDID = 2 */
+		uint64_t did:5; /* PCIe DID = 3 */
+		uint64_t io:1;	/* 1 for IO space access */
+		uint64_t reserved_49_61:13;	/* Must be zero */
+		uint64_t upper:2;	/* Normally 2 for XKPHYS */
+	} io;
+	struct {
+		uint64_t address:36;	/* PCIe Mem address */
+		uint64_t reserved_36_39:4;	/* Must be zero */
+		uint64_t subdid:3;	/* PCIe SubDID = 3-6 */
+		uint64_t did:5; /* PCIe DID = 3 */
+		uint64_t io:1;	/* 1 for IO space access */
+		uint64_t reserved_49_61:13;	/* Must be zero */
+		uint64_t upper:2;	/* Normally 2 for XKPHYS */
+	} mem;
+#endif
 };
 
+/* Endian swap mode. */
+#ifdef __BIG_ENDIAN_BITFIELD
+#define _CVMX_PCIE_ES 1
+#else
+#define _CVMX_PCIE_ES 0
+#endif
+
 static int cvmx_pcie_rc_initialize(int pcie_port);
 
 /**
@@ -102,7 +163,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port);
  *
  * Returns 64bit Octeon IO base address for read/write
  */
-static inline uint64_t cvmx_pcie_get_io_base_address(int pcie_port)
+static uint64_t cvmx_pcie_get_io_base_address(int pcie_port)
 {
 	union cvmx_pcie_address pcie_addr;
 	pcie_addr.u64 = 0;
@@ -110,7 +171,7 @@ static inline uint64_t cvmx_pcie_get_io_base_address(int pcie_port)
 	pcie_addr.io.io = 1;
 	pcie_addr.io.did = 3;
 	pcie_addr.io.subdid = 2;
-	pcie_addr.io.es = 1;
+	pcie_addr.io.es = _CVMX_PCIE_ES;
 	pcie_addr.io.port = pcie_port;
 	return pcie_addr.u64;
 }
@@ -241,7 +302,7 @@ static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus,
 	pcie_addr.config.io = 1;
 	pcie_addr.config.did = 3;
 	pcie_addr.config.subdid = 1;
-	pcie_addr.config.es = 1;
+	pcie_addr.config.es = _CVMX_PCIE_ES;
 	pcie_addr.config.port = pcie_port;
 	pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum);
 	pcie_addr.config.bus = bus;
@@ -889,8 +950,8 @@ static int __cvmx_pcie_rc_initialize_gen1(int pcie_port)
 	mem_access_subid.u64 = 0;
 	mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */
 	mem_access_subid.s.nmerge = 1;	/* Due to an errata on pass 1 chips, no merging is allowed. */
-	mem_access_subid.s.esr = 1;	/* Endian-swap for Reads. */
-	mem_access_subid.s.esw = 1;	/* Endian-swap for Writes. */
+	mem_access_subid.s.esr = _CVMX_PCIE_ES;	/* Endian-swap for Reads. */
+	mem_access_subid.s.esw = _CVMX_PCIE_ES;	/* Endian-swap for Writes. */
 	mem_access_subid.s.nsr = 0;	/* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */
 	mem_access_subid.s.nsw = 0;	/* Enable Snoop for Writes. */
 	mem_access_subid.s.ror = 0;	/* Disable Relaxed Ordering for Reads. */
@@ -925,7 +986,7 @@ static int __cvmx_pcie_rc_initialize_gen1(int pcie_port)
 	bar1_index.u32 = 0;
 	bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22);
 	bar1_index.s.ca = 1;	   /* Not Cached */
-	bar1_index.s.end_swp = 1;  /* Endian Swap mode */
+	bar1_index.s.end_swp = _CVMX_PCIE_ES;  /* Endian Swap mode */
 	bar1_index.s.addr_v = 1;   /* Valid entry */
 
 	base = pcie_port ? 16 : 0;
@@ -965,7 +1026,7 @@ static int __cvmx_pcie_rc_initialize_gen1(int pcie_port)
 		union cvmx_npei_ctl_port1 npei_ctl_port;
 		npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1);
 		npei_ctl_port.s.bar2_enb = 1;
-		npei_ctl_port.s.bar2_esx = 1;
+		npei_ctl_port.s.bar2_esx = _CVMX_PCIE_ES;
 		npei_ctl_port.s.bar2_cax = 0;
 		npei_ctl_port.s.ptlp_ro = 1;
 		npei_ctl_port.s.ctlp_ro = 1;
@@ -976,7 +1037,7 @@ static int __cvmx_pcie_rc_initialize_gen1(int pcie_port)
 		union cvmx_npei_ctl_port0 npei_ctl_port;
 		npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0);
 		npei_ctl_port.s.bar2_enb = 1;
-		npei_ctl_port.s.bar2_esx = 1;
+		npei_ctl_port.s.bar2_esx = _CVMX_PCIE_ES;
 		npei_ctl_port.s.bar2_cax = 0;
 		npei_ctl_port.s.ptlp_ro = 1;
 		npei_ctl_port.s.ctlp_ro = 1;
@@ -1341,8 +1402,8 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port)
 	mem_access_subid.u64 = 0;
 	mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */
 	mem_access_subid.s.nmerge = 0;	/* Allow merging as it works on CN6XXX. */
-	mem_access_subid.s.esr = 1;	/* Endian-swap for Reads. */
-	mem_access_subid.s.esw = 1;	/* Endian-swap for Writes. */
+	mem_access_subid.s.esr = _CVMX_PCIE_ES;	/* Endian-swap for Reads. */
+	mem_access_subid.s.esw = _CVMX_PCIE_ES;	/* Endian-swap for Writes. */
 	mem_access_subid.s.wtype = 0;	/* "No snoop" and "Relaxed ordering" are not set */
 	mem_access_subid.s.rtype = 0;	/* "No snoop" and "Relaxed ordering" are not set */
 	/* PCIe Adddress Bits <63:34>. */
@@ -1392,7 +1453,7 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port)
 	pemx_bar_ctl.u64 = cvmx_read_csr(CVMX_PEMX_BAR_CTL(pcie_port));
 	pemx_bar_ctl.s.bar1_siz = 3;  /* 256MB BAR1*/
 	pemx_bar_ctl.s.bar2_enb = 1;
-	pemx_bar_ctl.s.bar2_esx = 1;
+	pemx_bar_ctl.s.bar2_esx = _CVMX_PCIE_ES;
 	pemx_bar_ctl.s.bar2_cax = 0;
 	cvmx_write_csr(CVMX_PEMX_BAR_CTL(pcie_port), pemx_bar_ctl.u64);
 	sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port));
@@ -1408,7 +1469,7 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port)
 	bar1_index.u64 = 0;
 	bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22);
 	bar1_index.s.ca = 1;	   /* Not Cached */
-	bar1_index.s.end_swp = 1;  /* Endian Swap mode */
+	bar1_index.s.end_swp = _CVMX_PCIE_ES;  /* Endian Swap mode */
 	bar1_index.s.addr_v = 1;   /* Valid entry */
 
 	for (i = 0; i < 16; i++) {
-- 
2.28.0




[Index of Archives]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux