1 // SPDX-License-Identifier: GPL-2.0+ 2 // Copyright 2019 IBM Corp. 3 #include <linux/sched/mm.h> 4 #include "trace.h" 5 #include "ocxl_internal.h" 6 7 int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset, 8 enum ocxl_endian endian, u32 *val) 9 { 10 if (offset > afu->config.global_mmio_size - 4) 11 return -EINVAL; 12 13 #ifdef __BIG_ENDIAN__ 14 if (endian == OCXL_HOST_ENDIAN) 15 endian = OCXL_BIG_ENDIAN; 16 #endif 17 18 switch (endian) { 19 case OCXL_BIG_ENDIAN: 20 *val = readl_be((char *)afu->global_mmio_ptr + offset); 21 break; 22 23 default: 24 *val = readl((char *)afu->global_mmio_ptr + offset); 25 break; 26 } 27 28 return 0; 29 } 30 EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32); 31 32 int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset, 33 enum ocxl_endian endian, u64 *val) 34 { 35 if (offset > afu->config.global_mmio_size - 8) 36 return -EINVAL; 37 38 #ifdef __BIG_ENDIAN__ 39 if (endian == OCXL_HOST_ENDIAN) 40 endian = OCXL_BIG_ENDIAN; 41 #endif 42 43 switch (endian) { 44 case OCXL_BIG_ENDIAN: 45 *val = readq_be((char *)afu->global_mmio_ptr + offset); 46 break; 47 48 default: 49 *val = readq((char *)afu->global_mmio_ptr + offset); 50 break; 51 } 52 53 return 0; 54 } 55 EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64); 56 57 int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset, 58 enum ocxl_endian endian, u32 val) 59 { 60 if (offset > afu->config.global_mmio_size - 4) 61 return -EINVAL; 62 63 #ifdef __BIG_ENDIAN__ 64 if (endian == OCXL_HOST_ENDIAN) 65 endian = OCXL_BIG_ENDIAN; 66 #endif 67 68 switch (endian) { 69 case OCXL_BIG_ENDIAN: 70 writel_be(val, (char *)afu->global_mmio_ptr + offset); 71 break; 72 73 default: 74 writel(val, (char *)afu->global_mmio_ptr + offset); 75 break; 76 } 77 78 79 return 0; 80 } 81 EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32); 82 83 int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset, 84 enum ocxl_endian endian, u64 val) 85 { 86 if (offset > afu->config.global_mmio_size - 8) 87 return -EINVAL; 88 89 #ifdef __BIG_ENDIAN__ 90 if (endian == OCXL_HOST_ENDIAN) 91 endian = OCXL_BIG_ENDIAN; 92 #endif 93 94 switch (endian) { 95 case OCXL_BIG_ENDIAN: 96 writeq_be(val, (char *)afu->global_mmio_ptr + offset); 97 break; 98 99 default: 100 writeq(val, (char *)afu->global_mmio_ptr + offset); 101 break; 102 } 103 104 105 return 0; 106 } 107 EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64); 108 109 int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset, 110 enum ocxl_endian endian, u32 mask) 111 { 112 u32 tmp; 113 114 if (offset > afu->config.global_mmio_size - 4) 115 return -EINVAL; 116 117 #ifdef __BIG_ENDIAN__ 118 if (endian == OCXL_HOST_ENDIAN) 119 endian = OCXL_BIG_ENDIAN; 120 #endif 121 122 switch (endian) { 123 case OCXL_BIG_ENDIAN: 124 tmp = readl_be((char *)afu->global_mmio_ptr + offset); 125 tmp |= mask; 126 writel_be(tmp, (char *)afu->global_mmio_ptr + offset); 127 break; 128 129 default: 130 tmp = readl((char *)afu->global_mmio_ptr + offset); 131 tmp |= mask; 132 writel(tmp, (char *)afu->global_mmio_ptr + offset); 133 break; 134 } 135 136 return 0; 137 } 138 EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32); 139 140 int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset, 141 enum ocxl_endian endian, u64 mask) 142 { 143 u64 tmp; 144 145 if (offset > afu->config.global_mmio_size - 8) 146 return -EINVAL; 147 148 #ifdef __BIG_ENDIAN__ 149 if (endian == OCXL_HOST_ENDIAN) 150 endian = OCXL_BIG_ENDIAN; 151 #endif 152 153 switch (endian) { 154 case OCXL_BIG_ENDIAN: 155 tmp = readq_be((char *)afu->global_mmio_ptr + offset); 156 tmp |= mask; 157 writeq_be(tmp, (char *)afu->global_mmio_ptr + offset); 158 break; 159 160 default: 161 tmp = readq((char *)afu->global_mmio_ptr + offset); 162 tmp |= mask; 163 writeq(tmp, (char *)afu->global_mmio_ptr + offset); 164 break; 165 } 166 167 return 0; 168 } 169 EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64); 170 171 int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset, 172 enum ocxl_endian endian, u32 mask) 173 { 174 u32 tmp; 175 176 if (offset > afu->config.global_mmio_size - 4) 177 return -EINVAL; 178 179 #ifdef __BIG_ENDIAN__ 180 if (endian == OCXL_HOST_ENDIAN) 181 endian = OCXL_BIG_ENDIAN; 182 #endif 183 184 switch (endian) { 185 case OCXL_BIG_ENDIAN: 186 tmp = readl_be((char *)afu->global_mmio_ptr + offset); 187 tmp &= ~mask; 188 writel_be(tmp, (char *)afu->global_mmio_ptr + offset); 189 break; 190 191 default: 192 tmp = readl((char *)afu->global_mmio_ptr + offset); 193 tmp &= ~mask; 194 writel(tmp, (char *)afu->global_mmio_ptr + offset); 195 break; 196 } 197 198 199 return 0; 200 } 201 EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32); 202 203 int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset, 204 enum ocxl_endian endian, u64 mask) 205 { 206 u64 tmp; 207 208 if (offset > afu->config.global_mmio_size - 8) 209 return -EINVAL; 210 211 #ifdef __BIG_ENDIAN__ 212 if (endian == OCXL_HOST_ENDIAN) 213 endian = OCXL_BIG_ENDIAN; 214 #endif 215 216 switch (endian) { 217 case OCXL_BIG_ENDIAN: 218 tmp = readq_be((char *)afu->global_mmio_ptr + offset); 219 tmp &= ~mask; 220 writeq_be(tmp, (char *)afu->global_mmio_ptr + offset); 221 break; 222 223 default: 224 tmp = readq((char *)afu->global_mmio_ptr + offset); 225 tmp &= ~mask; 226 writeq(tmp, (char *)afu->global_mmio_ptr + offset); 227 break; 228 } 229 230 writeq(tmp, (char *)afu->global_mmio_ptr + offset); 231 232 return 0; 233 } 234 EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64); 235