^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * DMA implementation for Hexagon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/dma-map-ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/genalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static struct gen_pool *coherent_pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Allocates from a pool of uncached memory that was reserved at boot time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) gfp_t flag, unsigned long attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Our max_low_pfn should have been backed off by 16MB in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * mm/init.c to create DMA coherent space. Use that as the VA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * for the pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (coherent_pool == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (coherent_pool == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) panic("Can't create %s() memory pool!", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) gen_pool_add(coherent_pool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) (unsigned long)pfn_to_virt(max_low_pfn),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) hexagon_coherent_pool_size, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ret = (void *) gen_pool_alloc(coherent_pool, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) memset(ret, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *dma_addr = (dma_addr_t) virt_to_phys(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *dma_addr = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void arch_dma_free(struct device *dev, size_t size, void *vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) dma_addr_t dma_addr, unsigned long attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) enum dma_data_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) void *addr = phys_to_virt(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) switch (dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case DMA_TO_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) hexagon_clean_dcache_range((unsigned long) addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) (unsigned long) addr + size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case DMA_FROM_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) hexagon_inv_dcache_range((unsigned long) addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) (unsigned long) addr + size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case DMA_BIDIRECTIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) flush_dcache_range((unsigned long) addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) (unsigned long) addr + size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }