diff options
author | Huacai Chen <chenhc@lemote.com> | 2014-11-04 01:13:24 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:45:01 -0500 |
commit | f490682a6b21ffed5acd7a0d49d8371e5e625d7a (patch) | |
tree | 23fec41907ba1f5fb8cac1a5d2e0f18af6ee8fa7 | |
parent | 432d9ecb9628bdcb20670b2cf0678f3738bd40a5 (diff) |
MIPS: Loongson-3: Add PHYS48_TO_HT40 support
The width of HT-bus is only 40-bit, but Loongson-3 has 48-bit physical
address. This implies only node-0's memory is DMAable because high bits
(Node ID) will lost. Fortunately, by configuring address windows in
firmware, we can extract 2bit Node ID (bit 44~47, only bit 44~45 used
now) from Loongson-3's 48-bit address space and embed it into 40-bit
(bit 37~38). Every NUMA node can do DMA now (however, maximum memory of
each node is reduced to 2^37 = 128GB).
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Cc: John Crispin <john@phrozen.org>
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/8321/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/mach-loongson/dma-coherence.h | 6 | ||||
-rw-r--r-- | arch/mips/loongson/Kconfig | 5 | ||||
-rw-r--r-- | arch/mips/loongson/common/dma-swiotlb.c | 14 |
3 files changed, 22 insertions, 3 deletions
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h index 6a902751cc7f..a90534161bd2 100644 --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h | |||
@@ -23,7 +23,7 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, | |||
23 | size_t size) | 23 | size_t size) |
24 | { | 24 | { |
25 | #ifdef CONFIG_CPU_LOONGSON3 | 25 | #ifdef CONFIG_CPU_LOONGSON3 |
26 | return virt_to_phys(addr); | 26 | return phys_to_dma(dev, virt_to_phys(addr)); |
27 | #else | 27 | #else |
28 | return virt_to_phys(addr) | 0x80000000; | 28 | return virt_to_phys(addr) | 0x80000000; |
29 | #endif | 29 | #endif |
@@ -33,7 +33,7 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, | |||
33 | struct page *page) | 33 | struct page *page) |
34 | { | 34 | { |
35 | #ifdef CONFIG_CPU_LOONGSON3 | 35 | #ifdef CONFIG_CPU_LOONGSON3 |
36 | return page_to_phys(page); | 36 | return phys_to_dma(dev, page_to_phys(page)); |
37 | #else | 37 | #else |
38 | return page_to_phys(page) | 0x80000000; | 38 | return page_to_phys(page) | 0x80000000; |
39 | #endif | 39 | #endif |
@@ -43,7 +43,7 @@ static inline unsigned long plat_dma_addr_to_phys(struct device *dev, | |||
43 | dma_addr_t dma_addr) | 43 | dma_addr_t dma_addr) |
44 | { | 44 | { |
45 | #if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT) | 45 | #if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT) |
46 | return dma_addr; | 46 | return dma_to_phys(dev, dma_addr); |
47 | #elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) | 47 | #elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) |
48 | return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff); | 48 | return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff); |
49 | #else | 49 | #else |
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 1b91fc6a921b..72f830ac0782 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig | |||
@@ -86,6 +86,7 @@ config LOONGSON_MACH3X | |||
86 | select LOONGSON_MC146818 | 86 | select LOONGSON_MC146818 |
87 | select ZONE_DMA32 | 87 | select ZONE_DMA32 |
88 | select LEFI_FIRMWARE_INTERFACE | 88 | select LEFI_FIRMWARE_INTERFACE |
89 | select PHYS48_TO_HT40 | ||
89 | help | 90 | help |
90 | Generic Loongson 3 family machines utilize the 3A/3B revision | 91 | Generic Loongson 3 family machines utilize the 3A/3B revision |
91 | of Loongson processor and RS780/SBX00 chipset. | 92 | of Loongson processor and RS780/SBX00 chipset. |
@@ -131,6 +132,10 @@ config SWIOTLB | |||
131 | select NEED_SG_DMA_LENGTH | 132 | select NEED_SG_DMA_LENGTH |
132 | select NEED_DMA_MAP_STATE | 133 | select NEED_DMA_MAP_STATE |
133 | 134 | ||
135 | config PHYS48_TO_HT40 | ||
136 | bool | ||
137 | default y if CPU_LOONGSON3 | ||
138 | |||
134 | config LOONGSON_MC146818 | 139 | config LOONGSON_MC146818 |
135 | bool | 140 | bool |
136 | default n | 141 | default n |
diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c index c2be01f91575..2c6b989c1bc4 100644 --- a/arch/mips/loongson/common/dma-swiotlb.c +++ b/arch/mips/loongson/common/dma-swiotlb.c | |||
@@ -105,11 +105,25 @@ static int loongson_dma_set_mask(struct device *dev, u64 mask) | |||
105 | 105 | ||
106 | dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 106 | dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
107 | { | 107 | { |
108 | long nid; | ||
109 | #ifdef CONFIG_PHYS48_TO_HT40 | ||
110 | /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from | ||
111 | * Loongson-3's 48bit address space and embed it into 40bit */ | ||
112 | nid = (paddr >> 44) & 0x3; | ||
113 | paddr = ((nid << 44) ^ paddr) | (nid << 37); | ||
114 | #endif | ||
108 | return paddr; | 115 | return paddr; |
109 | } | 116 | } |
110 | 117 | ||
111 | phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) | 118 | phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) |
112 | { | 119 | { |
120 | long nid; | ||
121 | #ifdef CONFIG_PHYS48_TO_HT40 | ||
122 | /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from | ||
123 | * Loongson-3's 48bit address space and embed it into 40bit */ | ||
124 | nid = (daddr >> 37) & 0x3; | ||
125 | daddr = ((nid << 37) ^ daddr) | (nid << 44); | ||
126 | #endif | ||
113 | return daddr; | 127 | return daddr; |
114 | } | 128 | } |
115 | 129 | ||