// SPDX-License-Identifier: GPL-2.0+ // Copyright 2019 IBM Corp. #include <linux/sched/mm.h> #include "trace.h" #include "ocxl_internal.h" int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u32 *val) { if (offset > afu->config.global_mmio_size - 4) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: *val = readl_be((char *)afu->global_mmio_ptr + offset); break; default: *val = readl((char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32); int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u64 *val) { if (offset > afu->config.global_mmio_size - 8) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: *val = readq_be((char *)afu->global_mmio_ptr + offset); break; default: *val = readq((char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64); int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u32 val) { if (offset > afu->config.global_mmio_size - 4) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: writel_be(val, (char *)afu->global_mmio_ptr + offset); break; default: writel(val, (char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32); int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u64 val) { if (offset > afu->config.global_mmio_size - 8) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: writeq_be(val, (char *)afu->global_mmio_ptr + offset); break; default: writeq(val, (char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64); int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u32 mask) { u32 tmp; if (offset > afu->config.global_mmio_size - 4) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: tmp = readl_be((char *)afu->global_mmio_ptr + offset); tmp |= mask; writel_be(tmp, (char *)afu->global_mmio_ptr + offset); break; default: tmp = readl((char *)afu->global_mmio_ptr + offset); tmp |= mask; writel(tmp, (char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32); int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u64 mask) { u64 tmp; if (offset > afu->config.global_mmio_size - 8) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: tmp = readq_be((char *)afu->global_mmio_ptr + offset); tmp |= mask; writeq_be(tmp, (char *)afu->global_mmio_ptr + offset); break; default: tmp = readq((char *)afu->global_mmio_ptr + offset); tmp |= mask; writeq(tmp, (char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64); int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u32 mask) { u32 tmp; if (offset > afu->config.global_mmio_size - 4) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: tmp = readl_be((char *)afu->global_mmio_ptr + offset); tmp &= ~mask; writel_be(tmp, (char *)afu->global_mmio_ptr + offset); break; default: tmp = readl((char *)afu->global_mmio_ptr + offset); tmp &= ~mask; writel(tmp, (char *)afu->global_mmio_ptr + offset); break; } return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32); int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset, enum ocxl_endian endian, u64 mask) { u64 tmp; if (offset > afu->config.global_mmio_size - 8) return -EINVAL; #ifdef __BIG_ENDIAN__ if (endian == OCXL_HOST_ENDIAN) endian = OCXL_BIG_ENDIAN; #endif switch (endian) { case OCXL_BIG_ENDIAN: tmp = readq_be((char *)afu->global_mmio_ptr + offset); tmp &= ~mask; writeq_be(tmp, (char *)afu->global_mmio_ptr + offset); break; default: tmp = readq((char *)afu->global_mmio_ptr + offset); tmp &= ~mask; writeq(tmp, (char *)afu->global_mmio_ptr + offset); break; } writeq(tmp, (char *)afu->global_mmio_ptr + offset); return 0; } EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);