1db59e1b6SJean-Philippe Brucker // SPDX-License-Identifier: GPL-2.0-only 2db59e1b6SJean-Philippe Brucker #include <linux/acpi.h> 3db59e1b6SJean-Philippe Brucker #include <linux/acpi_iort.h> 4db59e1b6SJean-Philippe Brucker #include <linux/device.h> 5db59e1b6SJean-Philippe Brucker #include <linux/dma-direct.h> 6db59e1b6SJean-Philippe Brucker acpi_arch_dma_setup(struct device * dev)7*bf2ee8d0SJianmin Lvvoid acpi_arch_dma_setup(struct device *dev) 8db59e1b6SJean-Philippe Brucker { 9db59e1b6SJean-Philippe Brucker int ret; 10db59e1b6SJean-Philippe Brucker u64 end, mask; 11*bf2ee8d0SJianmin Lv u64 size = 0; 12*bf2ee8d0SJianmin Lv const struct bus_dma_region *map = NULL; 13db59e1b6SJean-Philippe Brucker 14db59e1b6SJean-Philippe Brucker /* 15db59e1b6SJean-Philippe Brucker * If @dev is expected to be DMA-capable then the bus code that created 16db59e1b6SJean-Philippe Brucker * it should have initialised its dma_mask pointer by this point. For 17db59e1b6SJean-Philippe Brucker * now, we'll continue the legacy behaviour of coercing it to the 18db59e1b6SJean-Philippe Brucker * coherent mask if not, but we'll no longer do so quietly. 19db59e1b6SJean-Philippe Brucker */ 20db59e1b6SJean-Philippe Brucker if (!dev->dma_mask) { 21db59e1b6SJean-Philippe Brucker dev_warn(dev, "DMA mask not set\n"); 22db59e1b6SJean-Philippe Brucker dev->dma_mask = &dev->coherent_dma_mask; 23db59e1b6SJean-Philippe Brucker } 24db59e1b6SJean-Philippe Brucker 25db59e1b6SJean-Philippe Brucker if (dev->coherent_dma_mask) 26db59e1b6SJean-Philippe Brucker size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); 27db59e1b6SJean-Philippe Brucker else 28db59e1b6SJean-Philippe Brucker size = 1ULL << 32; 29db59e1b6SJean-Philippe Brucker 30*bf2ee8d0SJianmin Lv ret = acpi_dma_get_range(dev, &map); 31*bf2ee8d0SJianmin Lv if (!ret && map) { 32*bf2ee8d0SJianmin Lv const struct bus_dma_region *r = map; 33*bf2ee8d0SJianmin Lv 34*bf2ee8d0SJianmin Lv for (end = 0; r->size; r++) { 35*bf2ee8d0SJianmin Lv if (r->dma_start + r->size - 1 > end) 36*bf2ee8d0SJianmin Lv end = r->dma_start + r->size - 1; 37*bf2ee8d0SJianmin Lv } 38*bf2ee8d0SJianmin Lv 39*bf2ee8d0SJianmin Lv size = end + 1; 40*bf2ee8d0SJianmin Lv dev->dma_range_map = map; 41*bf2ee8d0SJianmin Lv } 42*bf2ee8d0SJianmin Lv 43db59e1b6SJean-Philippe Brucker if (ret == -ENODEV) 44db59e1b6SJean-Philippe Brucker ret = iort_dma_get_ranges(dev, &size); 45db59e1b6SJean-Philippe Brucker if (!ret) { 46db59e1b6SJean-Philippe Brucker /* 47db59e1b6SJean-Philippe Brucker * Limit coherent and dma mask based on size retrieved from 48db59e1b6SJean-Philippe Brucker * firmware. 49db59e1b6SJean-Philippe Brucker */ 50*bf2ee8d0SJianmin Lv end = size - 1; 51db59e1b6SJean-Philippe Brucker mask = DMA_BIT_MASK(ilog2(end) + 1); 52db59e1b6SJean-Philippe Brucker dev->bus_dma_limit = end; 53db59e1b6SJean-Philippe Brucker dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask); 54db59e1b6SJean-Philippe Brucker *dev->dma_mask = min(*dev->dma_mask, mask); 55db59e1b6SJean-Philippe Brucker } 56db59e1b6SJean-Philippe Brucker } 57