mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 10:15:13 +07:00
68fbb9721e
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> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
29 lines
801 B
C
29 lines
801 B
C
// SPDX-License-Identifier: GPL-2.0
|
|
#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 << 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 >> node_id_offset) & 0x3;
|
|
|
|
return ((nid << node_id_offset) ^ daddr) | (nid << 44);
|
|
}
|
|
|
|
void __init plat_swiotlb_setup(void)
|
|
{
|
|
swiotlb_init(1);
|
|
}
|