Commit c78c43fe authored by Jianmin Lv's avatar Jianmin Lv Committed by Rafael J. Wysocki
Browse files

LoongArch: Use acpi_arch_dma_setup() and remove ARCH_HAS_PHYS_TO_DMA



Use _DMA defined in ACPI spec for translation between
DMA address and CPU address, and implement acpi_arch_dma_setup
for initializing dev->dma_range_map, where acpi_dma_get_range
is called for parsing _DMA.

e.g.
If we have two dma ranges:
cpu address      dma address    size         offset
0x200080000000   0x2080000000   0x400000000  0x1fe000000000
0x400080000000   0x4080000000   0x400000000  0x3fc000000000

_DMA for pci devices should be declared in host bridge as
flowing:

Name (_DMA, ResourceTemplate() {
        QWordMemory (ResourceProducer,
            PosDecode,
            MinFixed,
            MaxFixed,
            NonCacheable,
            ReadWrite,
            0x0,
            0x4080000000,
            0x447fffffff,
            0x3fc000000000,
            0x400000000,
            ,
            ,
            )

        QWordMemory (ResourceProducer,
            PosDecode,
            MinFixed,
            MaxFixed,
            NonCacheable,
            ReadWrite,
            0x0,
            0x2080000000,
            0x247fffffff,
            0x1fe000000000,
            0x400000000,
            ,
            ,
            )
    })

Acked-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
Signed-off-by: default avatarJianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent bf2ee8d0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ config LOONGARCH
	select ARCH_ENABLE_MEMORY_HOTPLUG
	select ARCH_ENABLE_MEMORY_HOTREMOVE
	select ARCH_HAS_ACPI_TABLE_UPGRADE	if ACPI
	select ARCH_HAS_PHYS_TO_DMA
	select ARCH_HAS_PTE_SPECIAL
	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
	select ARCH_INLINE_READ_LOCK if !PREEMPTION
+21 −31
Original line number Diff line number Diff line
@@ -2,39 +2,29 @@
/*
 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
 */
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/dma-direct.h>
#include <linux/dma-mapping.h>
#include <linux/dma-map-ops.h>
#include <linux/swiotlb.h>

#include <asm/bootinfo.h>
#include <asm/dma.h>
#include <asm/loongson.h>

/*
 * We extract 4bit node id (bit 44~47) from Loongson-3's
 * 48bit physical address space and embed it into 40bit.
 */

static int node_id_offset;

dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
void acpi_arch_dma_setup(struct device *dev)
{
	long nid = (paddr >> 44) & 0xf;
	int ret;
	u64 mask, end = 0;
	const struct bus_dma_region *map = NULL;

	return ((nid << 44) ^ paddr) | (nid << node_id_offset);
}
	ret = acpi_dma_get_range(dev, &map);
	if (!ret && map) {
		const struct bus_dma_region *r = map;

phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
{
	long nid = (daddr >> node_id_offset) & 0xf;
		for (end = 0; r->size; r++) {
			if (r->dma_start + r->size - 1 > end)
				end = r->dma_start + r->size - 1;
		}

	return ((nid << node_id_offset) ^ daddr) | (nid << 44);
		mask = DMA_BIT_MASK(ilog2(end) + 1);
		dev->bus_dma_limit = end;
		dev->dma_range_map = map;
		dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
		*dev->dma_mask = min(*dev->dma_mask, mask);
	}

void __init plat_swiotlb_setup(void)
{
	swiotlb_init(true, SWIOTLB_VERBOSE);
	node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36;
}
+1 −1
Original line number Diff line number Diff line
@@ -247,7 +247,7 @@ static void __init arch_mem_init(char **cmdline_p)
	sparse_init();
	memblock_set_bottom_up(true);

	plat_swiotlb_setup();
	swiotlb_init(true, SWIOTLB_VERBOSE);

	dma_contiguous_reserve(PFN_PHYS(max_low_pfn));

+6 −3
Original line number Diff line number Diff line
@@ -279,14 +279,17 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { }

void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);

#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
void acpi_arch_dma_setup(struct device *dev);
#else
static inline void acpi_arch_dma_setup(struct device *dev) { }
#endif

#ifdef CONFIG_ARM64
void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
void acpi_arch_dma_setup(struct device *dev);
#else
static inline void
acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
static inline void
acpi_arch_dma_setup(struct device *dev) { }
#endif

int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);