235 lines · c
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#endif17 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#endif42 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#endif67 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#endif93 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#endif121 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#endif152 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#endif183 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#endif215 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);235