linux/drivers/misc/ocxl/mmio.c
<<
>>
Prefs
   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);
 235