| 1 | /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ |
| 2 | /* Copyright (c) 2023 Imagination Technologies Ltd. */ |
| 3 | |
| 4 | #ifndef PVR_MMU_H |
| 5 | #define PVR_MMU_H |
| 6 | |
| 7 | #include <linux/memory.h> |
| 8 | #include <linux/types.h> |
| 9 | |
| 10 | /* Forward declaration from "pvr_device.h" */ |
| 11 | struct pvr_device; |
| 12 | |
| 13 | /* Forward declaration from "pvr_mmu.c" */ |
| 14 | struct pvr_mmu_context; |
| 15 | struct pvr_mmu_op_context; |
| 16 | |
| 17 | /* Forward declaration from "pvr_vm.c" */ |
| 18 | struct pvr_vm_context; |
| 19 | |
| 20 | /* Forward declaration from <linux/scatterlist.h> */ |
| 21 | struct sg_table; |
| 22 | |
| 23 | /** |
| 24 | * DOC: Public API (constants) |
| 25 | * |
| 26 | * .. c:macro:: PVR_DEVICE_PAGE_SIZE |
| 27 | * |
| 28 | * Fixed page size referenced by leaf nodes in the page table tree |
| 29 | * structure. In the current implementation, this value is pegged to the |
| 30 | * CPU page size (%PAGE_SIZE). It is therefore an error to specify a CPU |
| 31 | * page size which is not also a supported device page size. The supported |
| 32 | * device page sizes are: 4KiB, 16KiB, 64KiB, 256KiB, 1MiB and 2MiB. |
| 33 | * |
| 34 | * .. c:macro:: PVR_DEVICE_PAGE_SHIFT |
| 35 | * |
| 36 | * Shift value used to efficiently multiply or divide by |
| 37 | * %PVR_DEVICE_PAGE_SIZE. |
| 38 | * |
| 39 | * This value is derived from %PVR_DEVICE_PAGE_SIZE. |
| 40 | * |
| 41 | * .. c:macro:: PVR_DEVICE_PAGE_MASK |
| 42 | * |
| 43 | * Mask used to round a value down to the nearest multiple of |
| 44 | * %PVR_DEVICE_PAGE_SIZE. When bitwise negated, it will indicate whether a |
| 45 | * value is already a multiple of %PVR_DEVICE_PAGE_SIZE. |
| 46 | * |
| 47 | * This value is derived from %PVR_DEVICE_PAGE_SIZE. |
| 48 | */ |
| 49 | |
| 50 | /* PVR_DEVICE_PAGE_SIZE determines the page size */ |
| 51 | #define PVR_DEVICE_PAGE_SIZE (PAGE_SIZE) |
| 52 | #define PVR_DEVICE_PAGE_SHIFT (PAGE_SHIFT) |
| 53 | #define PVR_DEVICE_PAGE_MASK (PAGE_MASK) |
| 54 | |
| 55 | /** |
| 56 | * DOC: Page table index utilities (constants) |
| 57 | * |
| 58 | * .. c:macro:: PVR_PAGE_TABLE_ADDR_SPACE_SIZE |
| 59 | * |
| 60 | * Size of device-virtual address space which can be represented in the page |
| 61 | * table structure. |
| 62 | * |
| 63 | * This value is checked at runtime against |
| 64 | * &pvr_device_features.virtual_address_space_bits by |
| 65 | * pvr_vm_create_context(), which will return an error if the feature value |
| 66 | * does not match this constant. |
| 67 | * |
| 68 | * .. admonition:: Future work |
| 69 | * |
| 70 | * It should be possible to support other values of |
| 71 | * &pvr_device_features.virtual_address_space_bits, but so far no |
| 72 | * hardware has been created which advertises an unsupported value. |
| 73 | * |
| 74 | * .. c:macro:: PVR_PAGE_TABLE_ADDR_BITS |
| 75 | * |
| 76 | * Number of bits needed to represent any value less than |
| 77 | * %PVR_PAGE_TABLE_ADDR_SPACE_SIZE exactly. |
| 78 | * |
| 79 | * .. c:macro:: PVR_PAGE_TABLE_ADDR_MASK |
| 80 | * |
| 81 | * Bitmask of device-virtual addresses which are valid in the page table |
| 82 | * structure. |
| 83 | * |
| 84 | * This value is derived from %PVR_PAGE_TABLE_ADDR_SPACE_SIZE, so the same |
| 85 | * notes on that constant apply here. |
| 86 | */ |
| 87 | #define PVR_PAGE_TABLE_ADDR_SPACE_SIZE SZ_1T |
| 88 | #define PVR_PAGE_TABLE_ADDR_BITS __ffs(PVR_PAGE_TABLE_ADDR_SPACE_SIZE) |
| 89 | #define PVR_PAGE_TABLE_ADDR_MASK (PVR_PAGE_TABLE_ADDR_SPACE_SIZE - 1) |
| 90 | |
| 91 | void pvr_mmu_flush_request_all(struct pvr_device *pvr_dev); |
| 92 | int pvr_mmu_flush_exec(struct pvr_device *pvr_dev, bool wait); |
| 93 | |
| 94 | struct pvr_mmu_context *pvr_mmu_context_create(struct pvr_device *pvr_dev); |
| 95 | void pvr_mmu_context_destroy(struct pvr_mmu_context *ctx); |
| 96 | |
| 97 | dma_addr_t pvr_mmu_get_root_table_dma_addr(struct pvr_mmu_context *ctx); |
| 98 | |
| 99 | void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx); |
| 100 | struct pvr_mmu_op_context * |
| 101 | pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, |
| 102 | struct sg_table *sgt, u64 sgt_offset, u64 size); |
| 103 | |
| 104 | int pvr_mmu_map(struct pvr_mmu_op_context *op_ctx, u64 size, u64 flags, |
| 105 | u64 device_addr); |
| 106 | int pvr_mmu_unmap(struct pvr_mmu_op_context *op_ctx, u64 device_addr, u64 size); |
| 107 | |
| 108 | #endif /* PVR_MMU_H */ |
| 109 | |