xref: /openbmc/linux/drivers/misc/ocxl/mmio.c (revision 7e462c2a)
17e462c2aSAlastair D'Silva // SPDX-License-Identifier: GPL-2.0+
27e462c2aSAlastair D'Silva // Copyright 2019 IBM Corp.
37e462c2aSAlastair D'Silva #include <linux/sched/mm.h>
47e462c2aSAlastair D'Silva #include "trace.h"
57e462c2aSAlastair D'Silva #include "ocxl_internal.h"
67e462c2aSAlastair D'Silva 
ocxl_global_mmio_read32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 * val)77e462c2aSAlastair D'Silva int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset,
87e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u32 *val)
97e462c2aSAlastair D'Silva {
107e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 4)
117e462c2aSAlastair D'Silva 		return -EINVAL;
127e462c2aSAlastair D'Silva 
137e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
147e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
157e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
167e462c2aSAlastair D'Silva #endif
177e462c2aSAlastair D'Silva 
187e462c2aSAlastair D'Silva 	switch (endian) {
197e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
207e462c2aSAlastair D'Silva 		*val = readl_be((char *)afu->global_mmio_ptr + offset);
217e462c2aSAlastair D'Silva 		break;
227e462c2aSAlastair D'Silva 
237e462c2aSAlastair D'Silva 	default:
247e462c2aSAlastair D'Silva 		*val = readl((char *)afu->global_mmio_ptr + offset);
257e462c2aSAlastair D'Silva 		break;
267e462c2aSAlastair D'Silva 	}
277e462c2aSAlastair D'Silva 
287e462c2aSAlastair D'Silva 	return 0;
297e462c2aSAlastair D'Silva }
307e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32);
317e462c2aSAlastair D'Silva 
ocxl_global_mmio_read64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 * val)327e462c2aSAlastair D'Silva int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset,
337e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u64 *val)
347e462c2aSAlastair D'Silva {
357e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 8)
367e462c2aSAlastair D'Silva 		return -EINVAL;
377e462c2aSAlastair D'Silva 
387e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
397e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
407e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
417e462c2aSAlastair D'Silva #endif
427e462c2aSAlastair D'Silva 
437e462c2aSAlastair D'Silva 	switch (endian) {
447e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
457e462c2aSAlastair D'Silva 		*val = readq_be((char *)afu->global_mmio_ptr + offset);
467e462c2aSAlastair D'Silva 		break;
477e462c2aSAlastair D'Silva 
487e462c2aSAlastair D'Silva 	default:
497e462c2aSAlastair D'Silva 		*val = readq((char *)afu->global_mmio_ptr + offset);
507e462c2aSAlastair D'Silva 		break;
517e462c2aSAlastair D'Silva 	}
527e462c2aSAlastair D'Silva 
537e462c2aSAlastair D'Silva 	return 0;
547e462c2aSAlastair D'Silva }
557e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64);
567e462c2aSAlastair D'Silva 
ocxl_global_mmio_write32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 val)577e462c2aSAlastair D'Silva int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset,
587e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u32 val)
597e462c2aSAlastair D'Silva {
607e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 4)
617e462c2aSAlastair D'Silva 		return -EINVAL;
627e462c2aSAlastair D'Silva 
637e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
647e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
657e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
667e462c2aSAlastair D'Silva #endif
677e462c2aSAlastair D'Silva 
687e462c2aSAlastair D'Silva 	switch (endian) {
697e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
707e462c2aSAlastair D'Silva 		writel_be(val, (char *)afu->global_mmio_ptr + offset);
717e462c2aSAlastair D'Silva 		break;
727e462c2aSAlastair D'Silva 
737e462c2aSAlastair D'Silva 	default:
747e462c2aSAlastair D'Silva 		writel(val, (char *)afu->global_mmio_ptr + offset);
757e462c2aSAlastair D'Silva 		break;
767e462c2aSAlastair D'Silva 	}
777e462c2aSAlastair D'Silva 
787e462c2aSAlastair D'Silva 
797e462c2aSAlastair D'Silva 	return 0;
807e462c2aSAlastair D'Silva }
817e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32);
827e462c2aSAlastair D'Silva 
ocxl_global_mmio_write64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 val)837e462c2aSAlastair D'Silva int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset,
847e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u64 val)
857e462c2aSAlastair D'Silva {
867e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 8)
877e462c2aSAlastair D'Silva 		return -EINVAL;
887e462c2aSAlastair D'Silva 
897e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
907e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
917e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
927e462c2aSAlastair D'Silva #endif
937e462c2aSAlastair D'Silva 
947e462c2aSAlastair D'Silva 	switch (endian) {
957e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
967e462c2aSAlastair D'Silva 		writeq_be(val, (char *)afu->global_mmio_ptr + offset);
977e462c2aSAlastair D'Silva 		break;
987e462c2aSAlastair D'Silva 
997e462c2aSAlastair D'Silva 	default:
1007e462c2aSAlastair D'Silva 		writeq(val, (char *)afu->global_mmio_ptr + offset);
1017e462c2aSAlastair D'Silva 		break;
1027e462c2aSAlastair D'Silva 	}
1037e462c2aSAlastair D'Silva 
1047e462c2aSAlastair D'Silva 
1057e462c2aSAlastair D'Silva 	return 0;
1067e462c2aSAlastair D'Silva }
1077e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64);
1087e462c2aSAlastair D'Silva 
ocxl_global_mmio_set32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 mask)1097e462c2aSAlastair D'Silva int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset,
1107e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u32 mask)
1117e462c2aSAlastair D'Silva {
1127e462c2aSAlastair D'Silva 	u32 tmp;
1137e462c2aSAlastair D'Silva 
1147e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 4)
1157e462c2aSAlastair D'Silva 		return -EINVAL;
1167e462c2aSAlastair D'Silva 
1177e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
1187e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
1197e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
1207e462c2aSAlastair D'Silva #endif
1217e462c2aSAlastair D'Silva 
1227e462c2aSAlastair D'Silva 	switch (endian) {
1237e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
1247e462c2aSAlastair D'Silva 		tmp = readl_be((char *)afu->global_mmio_ptr + offset);
1257e462c2aSAlastair D'Silva 		tmp |= mask;
1267e462c2aSAlastair D'Silva 		writel_be(tmp, (char *)afu->global_mmio_ptr + offset);
1277e462c2aSAlastair D'Silva 		break;
1287e462c2aSAlastair D'Silva 
1297e462c2aSAlastair D'Silva 	default:
1307e462c2aSAlastair D'Silva 		tmp = readl((char *)afu->global_mmio_ptr + offset);
1317e462c2aSAlastair D'Silva 		tmp |= mask;
1327e462c2aSAlastair D'Silva 		writel(tmp, (char *)afu->global_mmio_ptr + offset);
1337e462c2aSAlastair D'Silva 		break;
1347e462c2aSAlastair D'Silva 	}
1357e462c2aSAlastair D'Silva 
1367e462c2aSAlastair D'Silva 	return 0;
1377e462c2aSAlastair D'Silva }
1387e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32);
1397e462c2aSAlastair D'Silva 
ocxl_global_mmio_set64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 mask)1407e462c2aSAlastair D'Silva int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset,
1417e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u64 mask)
1427e462c2aSAlastair D'Silva {
1437e462c2aSAlastair D'Silva 	u64 tmp;
1447e462c2aSAlastair D'Silva 
1457e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 8)
1467e462c2aSAlastair D'Silva 		return -EINVAL;
1477e462c2aSAlastair D'Silva 
1487e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
1497e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
1507e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
1517e462c2aSAlastair D'Silva #endif
1527e462c2aSAlastair D'Silva 
1537e462c2aSAlastair D'Silva 	switch (endian) {
1547e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
1557e462c2aSAlastair D'Silva 		tmp = readq_be((char *)afu->global_mmio_ptr + offset);
1567e462c2aSAlastair D'Silva 		tmp |= mask;
1577e462c2aSAlastair D'Silva 		writeq_be(tmp, (char *)afu->global_mmio_ptr + offset);
1587e462c2aSAlastair D'Silva 		break;
1597e462c2aSAlastair D'Silva 
1607e462c2aSAlastair D'Silva 	default:
1617e462c2aSAlastair D'Silva 		tmp = readq((char *)afu->global_mmio_ptr + offset);
1627e462c2aSAlastair D'Silva 		tmp |= mask;
1637e462c2aSAlastair D'Silva 		writeq(tmp, (char *)afu->global_mmio_ptr + offset);
1647e462c2aSAlastair D'Silva 		break;
1657e462c2aSAlastair D'Silva 	}
1667e462c2aSAlastair D'Silva 
1677e462c2aSAlastair D'Silva 	return 0;
1687e462c2aSAlastair D'Silva }
1697e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64);
1707e462c2aSAlastair D'Silva 
ocxl_global_mmio_clear32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 mask)1717e462c2aSAlastair D'Silva int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset,
1727e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u32 mask)
1737e462c2aSAlastair D'Silva {
1747e462c2aSAlastair D'Silva 	u32 tmp;
1757e462c2aSAlastair D'Silva 
1767e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 4)
1777e462c2aSAlastair D'Silva 		return -EINVAL;
1787e462c2aSAlastair D'Silva 
1797e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
1807e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
1817e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
1827e462c2aSAlastair D'Silva #endif
1837e462c2aSAlastair D'Silva 
1847e462c2aSAlastair D'Silva 	switch (endian) {
1857e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
1867e462c2aSAlastair D'Silva 		tmp = readl_be((char *)afu->global_mmio_ptr + offset);
1877e462c2aSAlastair D'Silva 		tmp &= ~mask;
1887e462c2aSAlastair D'Silva 		writel_be(tmp, (char *)afu->global_mmio_ptr + offset);
1897e462c2aSAlastair D'Silva 		break;
1907e462c2aSAlastair D'Silva 
1917e462c2aSAlastair D'Silva 	default:
1927e462c2aSAlastair D'Silva 		tmp = readl((char *)afu->global_mmio_ptr + offset);
1937e462c2aSAlastair D'Silva 		tmp &= ~mask;
1947e462c2aSAlastair D'Silva 		writel(tmp, (char *)afu->global_mmio_ptr + offset);
1957e462c2aSAlastair D'Silva 		break;
1967e462c2aSAlastair D'Silva 	}
1977e462c2aSAlastair D'Silva 
1987e462c2aSAlastair D'Silva 
1997e462c2aSAlastair D'Silva 	return 0;
2007e462c2aSAlastair D'Silva }
2017e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32);
2027e462c2aSAlastair D'Silva 
ocxl_global_mmio_clear64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 mask)2037e462c2aSAlastair D'Silva int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset,
2047e462c2aSAlastair D'Silva 				enum ocxl_endian endian, u64 mask)
2057e462c2aSAlastair D'Silva {
2067e462c2aSAlastair D'Silva 	u64 tmp;
2077e462c2aSAlastair D'Silva 
2087e462c2aSAlastair D'Silva 	if (offset > afu->config.global_mmio_size - 8)
2097e462c2aSAlastair D'Silva 		return -EINVAL;
2107e462c2aSAlastair D'Silva 
2117e462c2aSAlastair D'Silva #ifdef __BIG_ENDIAN__
2127e462c2aSAlastair D'Silva 	if (endian == OCXL_HOST_ENDIAN)
2137e462c2aSAlastair D'Silva 		endian = OCXL_BIG_ENDIAN;
2147e462c2aSAlastair D'Silva #endif
2157e462c2aSAlastair D'Silva 
2167e462c2aSAlastair D'Silva 	switch (endian) {
2177e462c2aSAlastair D'Silva 	case OCXL_BIG_ENDIAN:
2187e462c2aSAlastair D'Silva 		tmp = readq_be((char *)afu->global_mmio_ptr + offset);
2197e462c2aSAlastair D'Silva 		tmp &= ~mask;
2207e462c2aSAlastair D'Silva 		writeq_be(tmp, (char *)afu->global_mmio_ptr + offset);
2217e462c2aSAlastair D'Silva 		break;
2227e462c2aSAlastair D'Silva 
2237e462c2aSAlastair D'Silva 	default:
2247e462c2aSAlastair D'Silva 		tmp = readq((char *)afu->global_mmio_ptr + offset);
2257e462c2aSAlastair D'Silva 		tmp &= ~mask;
2267e462c2aSAlastair D'Silva 		writeq(tmp, (char *)afu->global_mmio_ptr + offset);
2277e462c2aSAlastair D'Silva 		break;
2287e462c2aSAlastair D'Silva 	}
2297e462c2aSAlastair D'Silva 
2307e462c2aSAlastair D'Silva 	writeq(tmp, (char *)afu->global_mmio_ptr + offset);
2317e462c2aSAlastair D'Silva 
2327e462c2aSAlastair D'Silva 	return 0;
2337e462c2aSAlastair D'Silva }
2347e462c2aSAlastair D'Silva EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);
235