linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7] MIPS: Loongson: Add DMA support for LS7A
@ 2020-05-08  8:36 Tiezhu Yang
  2020-05-08 13:02 ` Thomas Bogendoerfer
  0 siblings, 1 reply; 2+ messages in thread
From: Tiezhu Yang @ 2020-05-08  8:36 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Christoph Hellwig, Huacai Chen, Jiaxun Yang
  Cc: linux-mips, linux-kernel, Xuefeng Li

In the current market, the most used bridge chip on the Loongson platform
are RS780E and LS7A, the RS780E bridge chip is already supported by the
mainline kernel.

If use the default implementation of __phys_to_dma() and __dma_to_phys()
in dma-direct.h when CONFIG_ARCH_HAS_PHYS_TO_DMA is not set, it works
well used with LS7A on the Loongson single-way and multi-way platform,
and also works well used with RS780E on the Loongson single-way platform,
but the DMA address will be wrong on the non-node0 used with RS780E on
the Loongson multi-way platform.

Just as the description in the code comment, the devices get node id from
40 bit of HyperTransport bus, so we extract 2 bit node id (bit 44~45) from
48 bit address space of Loongson CPU and embed it into HyperTransport bus
(bit 37-38), this operation can be done only at the software level used
with RS780E on the Loongson multi-way platform, because it has no hardware
function to translate address of node id, this is a hardware compatibility
problem.

Device
    |
    | DMA address
    |
Host Bridge
    |
    | HT bus address (40 bit)
    |
   CPU
    |
    | physical address (48 bit)
    |
   RAM

The LS7A has dma_node_id_offset field in the DMA route config register,
the hardware can use the dma_node_id_offset to translate address of
node id automatically, so we can get correct address when just use the
dma_pfn_offset field in struct device.

For the above reasons, in order to maintain downward compatibility
to support the RS780E bridge chip, it is better to use the platform
dependent implementation of __phys_to_dma() and __dma_to_phys().

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---

v7:
  - According to the discussion of the v6 patch [1],
    use the platform dependent implementation of
    __phys_to_dma() and __dma_to_phys()
  - Make a slight modification based on the v4 patch [2]
    to put ls7a things before rs780e things

[1] https://lore.kernel.org/patchwork/patch/1233541/
[2] https://lore.kernel.org/patchwork/patch/1220010/

v6:
  - Make loongson_dma_config() static
  - Put ls7a things before rs780 things

v5:
  - Use the default implementation of __phys_to_dma()
    and __dma_to_phys() in dma-direct.h

v4:
  - Use LS7A instead of Loongson 7A1000 in the description
  - Use LS7A or ls7a instead of LS7A1000 or ls7a1000 in the code

v3:
  - Modify the macro definition NODE_ID_OFFSET_ADDR to
    make it easy to read
  - update the commit message

 arch/mips/include/asm/mach-loongson64/boot_param.h |  5 +++++
 arch/mips/loongson64/dma.c                         |  9 ++++++---
 arch/mips/loongson64/env.c                         |  2 ++
 arch/mips/loongson64/init.c                        | 17 +++++++++++++++++
 4 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index f082d87..b35be70 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -221,9 +221,14 @@ struct loongson_system_configuration {
 	u32 nr_sensors;
 	struct sensor_device sensors[MAX_SENSORS];
 	u64 workarounds;
+	void (*early_config)(void);
 };
 
 extern struct efi_memory_map_loongson *loongson_memmap;
 extern struct loongson_system_configuration loongson_sysconf;
 
+extern u32 node_id_offset;
+extern void ls7a_early_config(void);
+extern void rs780e_early_config(void);
+
 #endif
diff --git a/arch/mips/loongson64/dma.c b/arch/mips/loongson64/dma.c
index 5e86635..dbfe6e8 100644
--- a/arch/mips/loongson64/dma.c
+++ b/arch/mips/loongson64/dma.c
@@ -2,21 +2,24 @@
 #include <linux/dma-direct.h>
 #include <linux/init.h>
 #include <linux/swiotlb.h>
+#include <boot_param.h>
 
 dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
 	/* 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 */
 	long nid = (paddr >> 44) & 0x3;
-	return ((nid << 44) ^ paddr) | (nid << 37);
+
+	return ((nid << 44) ^ paddr) | (nid << node_id_offset);
 }
 
 phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
 	/* 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 */
-	long nid = (daddr >> 37) & 0x3;
-	return ((nid << 37) ^ daddr) | (nid << 44);
+	long nid = (daddr >> node_id_offset) & 0x3;
+
+	return ((nid << node_id_offset) ^ daddr) | (nid << 44);
 }
 
 void __init plat_swiotlb_setup(void)
diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
index 71f4aaf..d11bc34 100644
--- a/arch/mips/loongson64/env.c
+++ b/arch/mips/loongson64/env.c
@@ -192,8 +192,10 @@ void __init prom_init_env(void)
 	if (vendor == PCI_VENDOR_ID_LOONGSON && device == 0x7a00) {
 		pr_info("The bridge chip is LS7A\n");
 		loongson_sysconf.bridgetype = LS7A;
+		loongson_sysconf.early_config = ls7a_early_config;
 	} else {
 		pr_info("The bridge chip is RS780E or SR5690\n");
 		loongson_sysconf.bridgetype = RS780E;
+		loongson_sysconf.early_config = rs780e_early_config;
 	}
 }
diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index da38944..2b45ca6 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -13,6 +13,11 @@
 #include <asm/fw/fw.h>
 
 #include <loongson.h>
+#include <boot_param.h>
+
+#define NODE_ID_OFFSET_ADDR	((void __iomem *)TO_UNCAC(0x1001041c))
+
+u32 node_id_offset;
 
 static void __init mips_nmi_setup(void)
 {
@@ -24,6 +29,16 @@ static void __init mips_nmi_setup(void)
 	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
 }
 
+void ls7a_early_config(void)
+{
+	node_id_offset = ((readl(NODE_ID_OFFSET_ADDR) >> 8) & 0x1f) + 36;
+}
+
+void rs780e_early_config(void)
+{
+	node_id_offset = 37;
+}
+
 void __init prom_init(void)
 {
 	fw_init_cmdline();
@@ -33,6 +48,8 @@ void __init prom_init(void)
 	set_io_port_base((unsigned long)
 		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 
+	loongson_sysconf.early_config();
+
 	prom_init_numa_memory();
 
 	/* Hardcode to CPU UART 0 */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v7] MIPS: Loongson: Add DMA support for LS7A
  2020-05-08  8:36 [PATCH v7] MIPS: Loongson: Add DMA support for LS7A Tiezhu Yang
@ 2020-05-08 13:02 ` Thomas Bogendoerfer
  0 siblings, 0 replies; 2+ messages in thread
From: Thomas Bogendoerfer @ 2020-05-08 13:02 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Christoph Hellwig, Huacai Chen, Jiaxun Yang, linux-mips,
	linux-kernel, Xuefeng Li

On Fri, May 08, 2020 at 04:36:05PM +0800, Tiezhu Yang wrote:
> In the current market, the most used bridge chip on the Loongson platform
> are RS780E and LS7A, the RS780E bridge chip is already supported by the
> mainline kernel.
> 
> If use the default implementation of __phys_to_dma() and __dma_to_phys()
> in dma-direct.h when CONFIG_ARCH_HAS_PHYS_TO_DMA is not set, it works
> well used with LS7A on the Loongson single-way and multi-way platform,
> and also works well used with RS780E on the Loongson single-way platform,
> but the DMA address will be wrong on the non-node0 used with RS780E on
> the Loongson multi-way platform.
> 
> Just as the description in the code comment, the devices get node id from
> 40 bit of HyperTransport bus, so we extract 2 bit node id (bit 44~45) from
> 48 bit address space of Loongson CPU and embed it into HyperTransport bus
> (bit 37-38), this operation can be done only at the software level used
> with RS780E on the Loongson multi-way platform, because it has no hardware
> function to translate address of node id, this is a hardware compatibility
> problem.
> 
> Device
>     |
>     | DMA address
>     |
> Host Bridge
>     |
>     | HT bus address (40 bit)
>     |
>    CPU
>     |
>     | physical address (48 bit)
>     |
>    RAM
> 
> The LS7A has dma_node_id_offset field in the DMA route config register,
> the hardware can use the dma_node_id_offset to translate address of
> node id automatically, so we can get correct address when just use the
> dma_pfn_offset field in struct device.
> 
> For the above reasons, in order to maintain downward compatibility
> to support the RS780E bridge chip, it is better to use the platform
> dependent implementation of __phys_to_dma() and __dma_to_phys().
> 
> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
> 
> v7:
>   - According to the discussion of the v6 patch [1],
>     use the platform dependent implementation of
>     __phys_to_dma() and __dma_to_phys()
>   - Make a slight modification based on the v4 patch [2]
>     to put ls7a things before rs780e things
> 
> [1] https://lore.kernel.org/patchwork/patch/1233541/
> [2] https://lore.kernel.org/patchwork/patch/1220010/
> 
> v6:
>   - Make loongson_dma_config() static
>   - Put ls7a things before rs780 things
> 
> v5:
>   - Use the default implementation of __phys_to_dma()
>     and __dma_to_phys() in dma-direct.h
> 
> v4:
>   - Use LS7A instead of Loongson 7A1000 in the description
>   - Use LS7A or ls7a instead of LS7A1000 or ls7a1000 in the code
> 
> v3:
>   - Modify the macro definition NODE_ID_OFFSET_ADDR to
>     make it easy to read
>   - update the commit message
> 
>  arch/mips/include/asm/mach-loongson64/boot_param.h |  5 +++++
>  arch/mips/loongson64/dma.c                         |  9 ++++++---
>  arch/mips/loongson64/env.c                         |  2 ++
>  arch/mips/loongson64/init.c                        | 17 +++++++++++++++++
>  4 files changed, 30 insertions(+), 3 deletions(-)

applied to mips-next.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-05-08 13:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-08  8:36 [PATCH v7] MIPS: Loongson: Add DMA support for LS7A Tiezhu Yang
2020-05-08 13:02 ` Thomas Bogendoerfer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).