diff options
-rw-r--r-- | arch/mips/cavium-octeon/dma-octeon.c | 17 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 34 | ||||
-rw-r--r-- | arch/mips/include/asm/octeon/pci-octeon.h | 13 | ||||
-rw-r--r-- | arch/mips/pci/pcie-octeon.c | 37 |
4 files changed, 87 insertions, 14 deletions
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index be531ec1f206..d22b5a2d64f4 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c | |||
@@ -99,13 +99,16 @@ dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) | |||
99 | panic("dma_map_single: " | 99 | panic("dma_map_single: " |
100 | "Attempt to map illegal memory address 0x%llx\n", | 100 | "Attempt to map illegal memory address 0x%llx\n", |
101 | physical); | 101 | physical); |
102 | else if ((physical + size >= | 102 | else if (physical >= CVMX_PCIE_BAR1_PHYS_BASE && |
103 | (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20)) | 103 | physical + size < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE)) { |
104 | && physical < (4ull<<30)) | 104 | result = physical - CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_RC_BASE; |
105 | pr_warning("dma_map_single: Warning: " | 105 | |
106 | "Mapping memory address that might " | 106 | if (((result+size-1) & dma_mask) != result+size-1) |
107 | "conflict with devices 0x%llx-0x%llx\n", | 107 | panic("dma_map_single: Attempt to map address 0x%llx-0x%llx, which can't be accessed according to the dma mask 0x%llx\n", |
108 | physical, physical+size-1); | 108 | physical, physical+size-1, dma_mask); |
109 | goto done; | ||
110 | } | ||
111 | |||
109 | /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ | 112 | /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ |
110 | if ((physical >= 0x410000000ull) && physical < 0x420000000ull) | 113 | if ((physical >= 0x410000000ull) && physical < 0x420000000ull) |
111 | result = physical - 0x400000000ull; | 114 | result = physical - 0x400000000ull; |
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 041326e34f4d..69197cb6c7ea 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/time.h> | 32 | #include <asm/time.h> |
33 | 33 | ||
34 | #include <asm/octeon/octeon.h> | 34 | #include <asm/octeon/octeon.h> |
35 | #include <asm/octeon/pci-octeon.h> | ||
35 | 36 | ||
36 | #ifdef CONFIG_CAVIUM_DECODE_RSL | 37 | #ifdef CONFIG_CAVIUM_DECODE_RSL |
37 | extern void cvmx_interrupt_rsl_decode(void); | 38 | extern void cvmx_interrupt_rsl_decode(void); |
@@ -609,6 +610,22 @@ void __init prom_init(void) | |||
609 | register_smp_ops(&octeon_smp_ops); | 610 | register_smp_ops(&octeon_smp_ops); |
610 | } | 611 | } |
611 | 612 | ||
613 | /* Exclude a single page from the regions obtained in plat_mem_setup. */ | ||
614 | static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) | ||
615 | { | ||
616 | if (addr > *mem && addr < *mem + *size) { | ||
617 | u64 inc = addr - *mem; | ||
618 | add_memory_region(*mem, inc, BOOT_MEM_RAM); | ||
619 | *mem += inc; | ||
620 | *size -= inc; | ||
621 | } | ||
622 | |||
623 | if (addr == *mem && *size > PAGE_SIZE) { | ||
624 | *mem += PAGE_SIZE; | ||
625 | *size -= PAGE_SIZE; | ||
626 | } | ||
627 | } | ||
628 | |||
612 | void __init plat_mem_setup(void) | 629 | void __init plat_mem_setup(void) |
613 | { | 630 | { |
614 | uint64_t mem_alloc_size; | 631 | uint64_t mem_alloc_size; |
@@ -659,12 +676,27 @@ void __init plat_mem_setup(void) | |||
659 | CVMX_BOOTMEM_FLAG_NO_LOCKING); | 676 | CVMX_BOOTMEM_FLAG_NO_LOCKING); |
660 | #endif | 677 | #endif |
661 | if (memory >= 0) { | 678 | if (memory >= 0) { |
679 | u64 size = mem_alloc_size; | ||
680 | |||
681 | /* | ||
682 | * exclude a page at the beginning and end of | ||
683 | * the 256MB PCIe 'hole' so the kernel will not | ||
684 | * try to allocate multi-page buffers that | ||
685 | * span the discontinuity. | ||
686 | */ | ||
687 | memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE, | ||
688 | &memory, &size); | ||
689 | memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + | ||
690 | CVMX_PCIE_BAR1_PHYS_SIZE, | ||
691 | &memory, &size); | ||
692 | |||
662 | /* | 693 | /* |
663 | * This function automatically merges address | 694 | * This function automatically merges address |
664 | * regions next to each other if they are | 695 | * regions next to each other if they are |
665 | * received in incrementing order. | 696 | * received in incrementing order. |
666 | */ | 697 | */ |
667 | add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); | 698 | if (size) |
699 | add_memory_region(memory, size, BOOT_MEM_RAM); | ||
668 | total += mem_alloc_size; | 700 | total += mem_alloc_size; |
669 | } else { | 701 | } else { |
670 | break; | 702 | break; |
diff --git a/arch/mips/include/asm/octeon/pci-octeon.h b/arch/mips/include/asm/octeon/pci-octeon.h index 6ac5d3e3398e..ece78043acf6 100644 --- a/arch/mips/include/asm/octeon/pci-octeon.h +++ b/arch/mips/include/asm/octeon/pci-octeon.h | |||
@@ -15,6 +15,19 @@ | |||
15 | #define PCI_CONFIG_SPACE_DELAY 10000 | 15 | #define PCI_CONFIG_SPACE_DELAY 10000 |
16 | 16 | ||
17 | /* | 17 | /* |
18 | * The physical memory base mapped by BAR1. 256MB at the end of the | ||
19 | * first 4GB. | ||
20 | */ | ||
21 | #define CVMX_PCIE_BAR1_PHYS_BASE ((1ull << 32) - (1ull << 28)) | ||
22 | #define CVMX_PCIE_BAR1_PHYS_SIZE (1ull << 28) | ||
23 | |||
24 | /* | ||
25 | * The RC base of BAR1. gen1 has a 39-bit BAR2, gen2 has 41-bit BAR2, | ||
26 | * place BAR1 so it is the same for both. | ||
27 | */ | ||
28 | #define CVMX_PCIE_BAR1_RC_BASE (1ull << 41) | ||
29 | |||
30 | /* | ||
18 | * pcibios_map_irq() is defined inside pci-octeon.c. All it does is | 31 | * pcibios_map_irq() is defined inside pci-octeon.c. All it does is |
19 | * call the Octeon specific version pointed to by this variable. This | 32 | * call the Octeon specific version pointed to by this variable. This |
20 | * function needs to change for PCI or PCIe based hosts. | 33 | * function needs to change for PCI or PCIe based hosts. |
diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index 6aa5c542d52d..861361e0c9af 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c | |||
@@ -402,6 +402,10 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) | |||
402 | npei_ctl_status2.s.mps = 0; | 402 | npei_ctl_status2.s.mps = 0; |
403 | /* Max read request size = 128 bytes for best Octeon DMA performance */ | 403 | /* Max read request size = 128 bytes for best Octeon DMA performance */ |
404 | npei_ctl_status2.s.mrrs = 0; | 404 | npei_ctl_status2.s.mrrs = 0; |
405 | if (pcie_port) | ||
406 | npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ | ||
407 | else | ||
408 | npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ | ||
405 | cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); | 409 | cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); |
406 | 410 | ||
407 | /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ | 411 | /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ |
@@ -666,6 +670,8 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) | |||
666 | static int cvmx_pcie_rc_initialize(int pcie_port) | 670 | static int cvmx_pcie_rc_initialize(int pcie_port) |
667 | { | 671 | { |
668 | int i; | 672 | int i; |
673 | int base; | ||
674 | u64 addr_swizzle; | ||
669 | union cvmx_ciu_soft_prst ciu_soft_prst; | 675 | union cvmx_ciu_soft_prst ciu_soft_prst; |
670 | union cvmx_pescx_bist_status pescx_bist_status; | 676 | union cvmx_pescx_bist_status pescx_bist_status; |
671 | union cvmx_pescx_bist_status2 pescx_bist_status2; | 677 | union cvmx_pescx_bist_status2 pescx_bist_status2; |
@@ -674,6 +680,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port) | |||
674 | union cvmx_npei_mem_access_subidx mem_access_subid; | 680 | union cvmx_npei_mem_access_subidx mem_access_subid; |
675 | union cvmx_npei_dbg_data npei_dbg_data; | 681 | union cvmx_npei_dbg_data npei_dbg_data; |
676 | union cvmx_pescx_ctl_status2 pescx_ctl_status2; | 682 | union cvmx_pescx_ctl_status2 pescx_ctl_status2; |
683 | union cvmx_npei_bar1_indexx bar1_index; | ||
677 | 684 | ||
678 | /* | 685 | /* |
679 | * Make sure we aren't trying to setup a target mode interface | 686 | * Make sure we aren't trying to setup a target mode interface |
@@ -918,12 +925,30 @@ static int cvmx_pcie_rc_initialize(int pcie_port) | |||
918 | /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ | 925 | /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ |
919 | cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); | 926 | cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); |
920 | 927 | ||
921 | /* | 928 | /* BAR1 follows BAR2 with a gap. */ |
922 | * Disable Octeon's BAR1. It isn't needed in RC mode since | 929 | cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); |
923 | * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into | 930 | |
924 | * the 2nd 256MB of memory. | 931 | bar1_index.u32 = 0; |
925 | */ | 932 | bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); |
926 | cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); | 933 | bar1_index.s.ca = 1; /* Not Cached */ |
934 | bar1_index.s.end_swp = 1; /* Endian Swap mode */ | ||
935 | bar1_index.s.addr_v = 1; /* Valid entry */ | ||
936 | |||
937 | base = pcie_port ? 16 : 0; | ||
938 | |||
939 | /* Big endian swizzle for 32-bit PEXP_NCB register. */ | ||
940 | #ifdef __MIPSEB__ | ||
941 | addr_swizzle = 4; | ||
942 | #else | ||
943 | addr_swizzle = 0; | ||
944 | #endif | ||
945 | for (i = 0; i < 16; i++) { | ||
946 | cvmx_write64_uint32((CVMX_PEXP_NPEI_BAR1_INDEXX(base) ^ addr_swizzle), | ||
947 | bar1_index.u32); | ||
948 | base++; | ||
949 | /* 256MB / 16 >> 22 == 4 */ | ||
950 | bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); | ||
951 | } | ||
927 | 952 | ||
928 | /* | 953 | /* |
929 | * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take | 954 | * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take |