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