MIPS: Loongson-3: Add PHYS48_TO_HT40 support
authorHuacai Chen <chenhc@lemote.com>
Tue, 4 Nov 2014 06:13:24 +0000 (14:13 +0800)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 24 Nov 2014 06:45:01 +0000 (07:45 +0100)
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>
arch/mips/include/asm/mach-loongson/dma-coherence.h
arch/mips/loongson/Kconfig
arch/mips/loongson/common/dma-swiotlb.c

index 6a902751cc7f79034b802821857020a7386536e7..a90534161bd2e29a43ad8d66403dbf2f33ccaa3b 100644 (file)
@@ -23,7 +23,7 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
                                          size_t size)
 {
 #ifdef CONFIG_CPU_LOONGSON3
-       return virt_to_phys(addr);
+       return phys_to_dma(dev, virt_to_phys(addr));
 #else
        return virt_to_phys(addr) | 0x80000000;
 #endif
@@ -33,7 +33,7 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
                                               struct page *page)
 {
 #ifdef CONFIG_CPU_LOONGSON3
-       return page_to_phys(page);
+       return phys_to_dma(dev, page_to_phys(page));
 #else
        return page_to_phys(page) | 0x80000000;
 #endif
@@ -43,7 +43,7 @@ static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
        dma_addr_t dma_addr)
 {
 #if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
-       return dma_addr;
+       return dma_to_phys(dev, dma_addr);
 #elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
        return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
 #else
index 1b91fc6a921bca06f953ec9522c17fbd2f621ff7..72f830ac07820f025ac8a4fa90316d724233ef0d 100644 (file)
@@ -86,6 +86,7 @@ config LOONGSON_MACH3X
        select LOONGSON_MC146818
        select ZONE_DMA32
        select LEFI_FIRMWARE_INTERFACE
+       select PHYS48_TO_HT40
        help
                Generic Loongson 3 family machines utilize the 3A/3B revision
                of Loongson processor and RS780/SBX00 chipset.
@@ -131,6 +132,10 @@ config SWIOTLB
        select NEED_SG_DMA_LENGTH
        select NEED_DMA_MAP_STATE
 
+config PHYS48_TO_HT40
+       bool
+       default y if CPU_LOONGSON3
+
 config LOONGSON_MC146818
        bool
        default n
index c2be01f915754b0514575046aa8b1a996e1b8e6d..2c6b989c1bc4054c354b65fc0fbded4ac8c52b66 100644 (file)
@@ -105,11 +105,25 @@ static int loongson_dma_set_mask(struct device *dev, u64 mask)
 
 dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
+       long nid;
+#ifdef CONFIG_PHYS48_TO_HT40
+       /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from
+        * Loongson-3's 48bit address space and embed it into 40bit */
+       nid = (paddr >> 44) & 0x3;
+       paddr = ((nid << 44) ^ paddr) | (nid << 37);
+#endif
        return paddr;
 }
 
 phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
+       long nid;
+#ifdef CONFIG_PHYS48_TO_HT40
+       /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from
+        * Loongson-3's 48bit address space and embed it into 40bit */
+       nid = (daddr >> 37) & 0x3;
+       daddr = ((nid << 37) ^ daddr) | (nid << 44);
+#endif
        return daddr;
 }