1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> 7 */ 8 9 #include <linux/device.h> 10 #include <linux/dma-direction.h> 11 #include <linux/dma-mapping.h> 12 #include <linux/init.h> 13 #include <linux/mm.h> 14 #include <linux/of.h> 15 #include <linux/pci.h> 16 #include <linux/types.h> 17 #include <dma-coherence.h> 18 19 /* 20 * BCM3384 has configurable address translation windows which allow the 21 * peripherals' DMA addresses to be different from the Zephyr-visible 22 * physical addresses. e.g. usb_dma_addr = zephyr_pa ^ 0x08000000 23 * 24 * If our DT "memory" node has a "dma-xor-mask" property we will enable this 25 * translation using the provided offset. 26 */ 27 static u32 bcm3384_dma_xor_mask; 28 static u32 bcm3384_dma_xor_limit = 0xffffffff; 29 30 /* 31 * PCI collapses the memory hole at 0x10000000 - 0x1fffffff. 32 * On systems with a dma-xor-mask, this range is guaranteed to live above 33 * the dma-xor-limit. 34 */ 35 #define BCM3384_MEM_HOLE_PA 0x10000000 36 #define BCM3384_MEM_HOLE_SIZE 0x10000000 37 38 static dma_addr_t bcm3384_phys_to_dma(struct device *dev, phys_addr_t pa) 39 { 40 if (dev && dev_is_pci(dev) && 41 pa >= (BCM3384_MEM_HOLE_PA + BCM3384_MEM_HOLE_SIZE)) 42 return pa - BCM3384_MEM_HOLE_SIZE; 43 if (pa <= bcm3384_dma_xor_limit) 44 return pa ^ bcm3384_dma_xor_mask; 45 return pa; 46 } 47 48 dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) 49 { 50 return bcm3384_phys_to_dma(dev, virt_to_phys(addr)); 51 } 52 53 dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) 54 { 55 return bcm3384_phys_to_dma(dev, page_to_phys(page)); 56 } 57 58 unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) 59 { 60 if (dev && dev_is_pci(dev) && 61 dma_addr >= BCM3384_MEM_HOLE_PA) 62 return dma_addr + BCM3384_MEM_HOLE_SIZE; 63 if ((dma_addr ^ bcm3384_dma_xor_mask) <= bcm3384_dma_xor_limit) 64 return dma_addr ^ bcm3384_dma_xor_mask; 65 return dma_addr; 66 } 67 68 static int __init bcm3384_init_dma_xor(void) 69 { 70 struct device_node *np = of_find_node_by_type(NULL, "memory"); 71 72 if (!np) 73 return 0; 74 75 of_property_read_u32(np, "dma-xor-mask", &bcm3384_dma_xor_mask); 76 of_property_read_u32(np, "dma-xor-limit", &bcm3384_dma_xor_limit); 77 78 of_node_put(np); 79 return 0; 80 } 81 arch_initcall(bcm3384_init_dma_xor); 82