mmio.c (4878B)
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 7int 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} 30EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32); 31 32int 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} 55EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64); 56 57int 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} 81EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32); 82 83int 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} 107EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64); 108 109int 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} 138EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32); 139 140int 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} 169EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64); 170 171int 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} 201EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32); 202 203int 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} 234EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);