1*3318a794SDaniel Machon /* SPDX-License-Identifier: GPL-2.0+ */ 2*3318a794SDaniel Machon 3*3318a794SDaniel Machon #ifndef _FDMA_PCI_H_ 4*3318a794SDaniel Machon #define _FDMA_PCI_H_ 5*3318a794SDaniel Machon 6*3318a794SDaniel Machon #include <linux/align.h> 7*3318a794SDaniel Machon #include <linux/bits.h> 8*3318a794SDaniel Machon #include <linux/mutex.h> 9*3318a794SDaniel Machon #include <linux/types.h> 10*3318a794SDaniel Machon 11*3318a794SDaniel Machon #define FDMA_PCI_ATU_REGION_MAX 6 12*3318a794SDaniel Machon 13*3318a794SDaniel Machon /* Outbound regions are 64KB granular (datasheet section 3.24.7.4.1), so both 14*3318a794SDaniel Machon * the region base and the mapped size must be aligned to this. 15*3318a794SDaniel Machon */ 16*3318a794SDaniel Machon #define FDMA_PCI_ATU_REGION_ALIGN BIT(16) 17*3318a794SDaniel Machon 18*3318a794SDaniel Machon #define FDMA_PCI_DB_ALIGN 128 19*3318a794SDaniel Machon #define FDMA_PCI_DB_SIZE(mtu) ALIGN(mtu, FDMA_PCI_DB_ALIGN) 20*3318a794SDaniel Machon 21*3318a794SDaniel Machon struct fdma_pci_atu; 22*3318a794SDaniel Machon 23*3318a794SDaniel Machon struct fdma_pci_atu_region { 24*3318a794SDaniel Machon struct fdma_pci_atu *atu; 25*3318a794SDaniel Machon u64 base_addr; /* Base addr of the OB window */ 26*3318a794SDaniel Machon u64 limit_addr; /* End addr of the active mapping (base_addr + size - 1) */ 27*3318a794SDaniel Machon u64 target_addr; /* Host DMA address this region maps to */ 28*3318a794SDaniel Machon int idx; 29*3318a794SDaniel Machon bool in_use; 30*3318a794SDaniel Machon }; 31*3318a794SDaniel Machon 32*3318a794SDaniel Machon struct fdma_pci_atu { 33*3318a794SDaniel Machon void __iomem *addr; 34*3318a794SDaniel Machon struct mutex lock; /* Protects region alloc/free and ATU register access */ 35*3318a794SDaniel Machon struct fdma_pci_atu_region regions[FDMA_PCI_ATU_REGION_MAX]; 36*3318a794SDaniel Machon }; 37*3318a794SDaniel Machon 38*3318a794SDaniel Machon /* Initialize ATU, dividing OB space into regions. */ 39*3318a794SDaniel Machon void fdma_pci_atu_init(struct fdma_pci_atu *atu, void __iomem *addr); 40*3318a794SDaniel Machon 41*3318a794SDaniel Machon /* Unmap an ATU region, clearing its translation and disabling it. */ 42*3318a794SDaniel Machon void fdma_pci_atu_region_unmap(struct fdma_pci_atu_region *region); 43*3318a794SDaniel Machon 44*3318a794SDaniel Machon /* Map a host DMA address into a free ATU region. target_addr and size must be 45*3318a794SDaniel Machon * FDMA_PCI_ATU_REGION_ALIGN aligned; a misaligned target_addr returns -EINVAL. 46*3318a794SDaniel Machon */ 47*3318a794SDaniel Machon struct fdma_pci_atu_region *fdma_pci_atu_region_map(struct fdma_pci_atu *atu, 48*3318a794SDaniel Machon u64 target_addr, 49*3318a794SDaniel Machon int size); 50*3318a794SDaniel Machon 51*3318a794SDaniel Machon /* Translate a host DMA address to the OB address space. Reads the region 52*3318a794SDaniel Machon * unlocked, so the caller must quiesce DMA and the descriptor paths before 53*3318a794SDaniel Machon * unmapping the region. 54*3318a794SDaniel Machon */ 55*3318a794SDaniel Machon u64 fdma_pci_atu_translate_addr(struct fdma_pci_atu_region *region, u64 addr); 56*3318a794SDaniel Machon 57*3318a794SDaniel Machon #endif 58