• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
ocxl_global_mmio_read32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 * val)7  int 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  }
30  EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32);
31  
ocxl_global_mmio_read64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 * val)32  int 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  }
55  EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64);
56  
ocxl_global_mmio_write32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 val)57  int 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  }
81  EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32);
82  
ocxl_global_mmio_write64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 val)83  int 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  }
107  EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64);
108  
ocxl_global_mmio_set32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 mask)109  int 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  }
138  EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32);
139  
ocxl_global_mmio_set64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 mask)140  int 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  }
169  EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64);
170  
ocxl_global_mmio_clear32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 mask)171  int 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  }
201  EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32);
202  
ocxl_global_mmio_clear64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 mask)203  int 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  }
234  EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);
235