1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * Copyright (C) 2020 Stefan Roese <sr@denx.de>
4 */
5
6 #ifndef __CVMX_REGS_H__
7 #define __CVMX_REGS_H__
8
9 #include <linux/bitfield.h>
10 #include <linux/bitops.h>
11 #include <linux/io.h>
12 #include <mach/cvmx-address.h>
13
14 /* General defines */
15 #define CVMX_MAX_CORES 48
16 /* Maximum # of bits to define core in node */
17 #define CVMX_NODE_NO_SHIFT 7
18 #define CVMX_NODE_BITS 2 /* Number of bits to define a node */
19 #define CVMX_MAX_NODES (1 << CVMX_NODE_BITS)
20 #define CVMX_NODE_MASK (CVMX_MAX_NODES - 1)
21 #define CVMX_NODE_IO_SHIFT 36
22 #define CVMX_NODE_MEM_SHIFT 40
23 #define CVMX_NODE_IO_MASK ((u64)CVMX_NODE_MASK << CVMX_NODE_IO_SHIFT)
24
25 #define CVMX_MIPS_MAX_CORE_BITS 10 /* Maximum # of bits to define cores */
26 #define CVMX_MIPS_MAX_CORES (1 << CVMX_MIPS_MAX_CORE_BITS)
27
28 #define MAX_CORE_TADS 8
29
30 #define CASTPTR(type, v) ((type *)(long)(v))
31 #define CAST64(v) ((long long)(long)(v))
32
33 /* Regs */
34 #define CVMX_CIU3_NMI 0x0001010000000160ULL
35
36 #define CVMX_MIO_BOOT_LOC_CFGX(x) (0x0001180000000080ULL + ((x) & 1) * 8)
37 #define MIO_BOOT_LOC_CFG_BASE GENMASK_ULL(27, 3)
38 #define MIO_BOOT_LOC_CFG_EN BIT_ULL(31)
39
40 #define CVMX_MIO_BOOT_LOC_ADR 0x0001180000000090ULL
41 #define MIO_BOOT_LOC_ADR_ADR GENMASK_ULL(7, 3)
42
43 #define CVMX_MIO_BOOT_LOC_DAT 0x0001180000000098ULL
44
45 #define CVMX_MIO_FUS_DAT2 0x0001180000001410ULL
46 #define MIO_FUS_DAT2_NOCRYPTO BIT_ULL(26)
47 #define MIO_FUS_DAT2_NOMUL BIT_ULL(27)
48 #define MIO_FUS_DAT2_DORM_CRYPTO BIT_ULL(34)
49
50 #define CVMX_MIO_FUS_RCMD 0x0001180000001500ULL
51 #define MIO_FUS_RCMD_ADDR GENMASK_ULL(7, 0)
52 #define MIO_FUS_RCMD_PEND BIT_ULL(12)
53 #define MIO_FUS_RCMD_DAT GENMASK_ULL(23, 16)
54
55 #define CVMX_RNM_CTL_STATUS 0x0001180040000000ULL
56 #define RNM_CTL_STATUS_EER_VAL BIT_ULL(9)
57
58 #define CVMX_IOBDMA_ORDERED_IO_ADDR 0xffffffffffffa200ull
59
60 /* turn the variable name into a string */
61 #define CVMX_TMP_STR(x) CVMX_TMP_STR2(x)
62 #define CVMX_TMP_STR2(x) #x
63
64 #define CVMX_RDHWR(result, regstr) \
65 asm volatile("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d"(result))
66 #define CVMX_RDHWRNV(result, regstr) \
67 asm("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d"(result))
68 #define CVMX_POP(result, input) \
69 asm("pop %[rd],%[rs]" : [rd] "=d"(result) : [rs] "d"(input))
70
71 #define CVMX_SYNC asm volatile("sync\n" : : : "memory")
72 #define CVMX_SYNCW asm volatile("syncw\nsyncw\n" : : : "memory")
73 #define CVMX_SYNCS asm volatile("syncs\n" : : : "memory")
74 #define CVMX_SYNCWS asm volatile("syncws\n" : : : "memory")
75
76 #define CVMX_CACHE_LINE_SIZE 128 // In bytes
77 #define CVMX_CACHE_LINE_MASK (CVMX_CACHE_LINE_SIZE - 1) // In bytes
78 #define CVMX_CACHE_LINE_ALIGNED __aligned(CVMX_CACHE_LINE_SIZE)
79
80 #define CVMX_SYNCIOBDMA asm volatile("synciobdma" : : : "memory")
81
82 #define CVMX_MF_CHORD(dest) CVMX_RDHWR(dest, 30)
83
84 /*
85 * The macros cvmx_likely and cvmx_unlikely use the
86 * __builtin_expect GCC operation to control branch
87 * probabilities for a conditional. For example, an "if"
88 * statement in the code that will almost always be
89 * executed should be written as "if (cvmx_likely(...))".
90 * If the "else" section of an if statement is more
91 * probable, use "if (cvmx_unlikey(...))".
92 */
93 #define cvmx_likely(x) __builtin_expect(!!(x), 1)
94 #define cvmx_unlikely(x) __builtin_expect(!!(x), 0)
95
96 #define CVMX_WAIT_FOR_FIELD64(address, type, field, op, value, to_us) \
97 ({ \
98 int result; \
99 do { \
100 u64 done = get_timer(0); \
101 type c; \
102 while (1) { \
103 c.u64 = csr_rd(address); \
104 if ((c.s.field)op(value)) { \
105 result = 0; \
106 break; \
107 } else if (get_timer(done) > ((to_us) / 1000)) { \
108 result = -1; \
109 break; \
110 } else \
111 udelay(100); \
112 } \
113 } while (0); \
114 result; \
115 })
116
117 #define CVMX_WAIT_FOR_FIELD64_NODE(node, address, type, field, op, value, to_us) \
118 ({ \
119 int result; \
120 do { \
121 u64 done = get_timer(0); \
122 type c; \
123 while (1) { \
124 c.u64 = csr_rd(address); \
125 if ((c.s.field)op(value)) { \
126 result = 0; \
127 break; \
128 } else if (get_timer(done) > ((to_us) / 1000)) { \
129 result = -1; \
130 break; \
131 } else \
132 udelay(100); \
133 } \
134 } while (0); \
135 result; \
136 })
137
138 /* ToDo: Currently only node = 0 supported */
139 #define cvmx_get_node_num() 0
140
csr_rd_node(int node,u64 addr)141 static inline u64 csr_rd_node(int node, u64 addr)
142 {
143 void __iomem *base;
144
145 base = ioremap_nocache(addr, 0x100);
146 return ioread64(base);
147 }
148
csr_rd32_node(int node,u64 addr)149 static inline u32 csr_rd32_node(int node, u64 addr)
150 {
151 void __iomem *base;
152
153 base = ioremap_nocache(addr, 0x100);
154 return ioread32(base);
155 }
156
csr_rd(u64 addr)157 static inline u64 csr_rd(u64 addr)
158 {
159 return csr_rd_node(0, addr);
160 }
161
csr_rd32(u64 addr)162 static inline u32 csr_rd32(u64 addr)
163 {
164 return csr_rd32_node(0, addr);
165 }
166
csr_wr_node(int node,u64 addr,u64 val)167 static inline void csr_wr_node(int node, u64 addr, u64 val)
168 {
169 void __iomem *base;
170
171 base = ioremap_nocache(addr, 0x100);
172 iowrite64(val, base);
173 }
174
csr_wr32_node(int node,u64 addr,u32 val)175 static inline void csr_wr32_node(int node, u64 addr, u32 val)
176 {
177 void __iomem *base;
178
179 base = ioremap_nocache(addr, 0x100);
180 iowrite32(val, base);
181 }
182
csr_wr(u64 addr,u64 val)183 static inline void csr_wr(u64 addr, u64 val)
184 {
185 csr_wr_node(0, addr, val);
186 }
187
csr_wr32(u64 addr,u32 val)188 static inline void csr_wr32(u64 addr, u32 val)
189 {
190 csr_wr32_node(0, addr, val);
191 }
192
193 /*
194 * We need to use the volatile access here, otherwise the IO accessor
195 * functions might swap the bytes
196 */
cvmx_read64_uint64(u64 addr)197 static inline u64 cvmx_read64_uint64(u64 addr)
198 {
199 return *(volatile u64 *)addr;
200 }
201
cvmx_read64_int64(u64 addr)202 static inline s64 cvmx_read64_int64(u64 addr)
203 {
204 return *(volatile s64 *)addr;
205 }
206
cvmx_write64_uint64(u64 addr,u64 val)207 static inline void cvmx_write64_uint64(u64 addr, u64 val)
208 {
209 *(volatile u64 *)addr = val;
210 }
211
cvmx_write64_int64(u64 addr,s64 val)212 static inline void cvmx_write64_int64(u64 addr, s64 val)
213 {
214 *(volatile s64 *)addr = val;
215 }
216
cvmx_read64_uint32(u64 addr)217 static inline u32 cvmx_read64_uint32(u64 addr)
218 {
219 return *(volatile u32 *)addr;
220 }
221
cvmx_read64_int32(u64 addr)222 static inline s32 cvmx_read64_int32(u64 addr)
223 {
224 return *(volatile s32 *)addr;
225 }
226
cvmx_write64_uint32(u64 addr,u32 val)227 static inline void cvmx_write64_uint32(u64 addr, u32 val)
228 {
229 *(volatile u32 *)addr = val;
230 }
231
cvmx_write64_int32(u64 addr,s32 val)232 static inline void cvmx_write64_int32(u64 addr, s32 val)
233 {
234 *(volatile s32 *)addr = val;
235 }
236
cvmx_write64_int16(u64 addr,s16 val)237 static inline void cvmx_write64_int16(u64 addr, s16 val)
238 {
239 *(volatile s16 *)addr = val;
240 }
241
cvmx_write64_uint16(u64 addr,u16 val)242 static inline void cvmx_write64_uint16(u64 addr, u16 val)
243 {
244 *(volatile u16 *)addr = val;
245 }
246
cvmx_write64_int8(u64 addr,int8_t val)247 static inline void cvmx_write64_int8(u64 addr, int8_t val)
248 {
249 *(volatile int8_t *)addr = val;
250 }
251
cvmx_write64_uint8(u64 addr,u8 val)252 static inline void cvmx_write64_uint8(u64 addr, u8 val)
253 {
254 *(volatile u8 *)addr = val;
255 }
256
cvmx_read64_int16(u64 addr)257 static inline s16 cvmx_read64_int16(u64 addr)
258 {
259 return *(volatile s16 *)addr;
260 }
261
cvmx_read64_uint16(u64 addr)262 static inline u16 cvmx_read64_uint16(u64 addr)
263 {
264 return *(volatile u16 *)addr;
265 }
266
cvmx_read64_int8(u64 addr)267 static inline int8_t cvmx_read64_int8(u64 addr)
268 {
269 return *(volatile int8_t *)addr;
270 }
271
cvmx_read64_uint8(u64 addr)272 static inline u8 cvmx_read64_uint8(u64 addr)
273 {
274 return *(volatile u8 *)addr;
275 }
276
cvmx_send_single(u64 data)277 static inline void cvmx_send_single(u64 data)
278 {
279 cvmx_write64_uint64(CVMX_IOBDMA_ORDERED_IO_ADDR, data);
280 }
281
282 /**
283 * Perform a 64-bit write to an IO address
284 *
285 * @param io_addr I/O address to write to
286 * @param val 64-bit value to write
287 */
cvmx_write_io(u64 io_addr,u64 val)288 static inline void cvmx_write_io(u64 io_addr, u64 val)
289 {
290 cvmx_write64_uint64(io_addr, val);
291 }
292
293 /**
294 * Builds a memory address for I/O based on the Major and Sub DID.
295 *
296 * @param major_did 5 bit major did
297 * @param sub_did 3 bit sub did
298 * @return I/O base address
299 */
cvmx_build_io_address(u64 major_did,u64 sub_did)300 static inline u64 cvmx_build_io_address(u64 major_did, u64 sub_did)
301 {
302 return ((0x1ull << 48) | (major_did << 43) | (sub_did << 40));
303 }
304
305 /**
306 * Builds a bit mask given the required size in bits.
307 *
308 * @param bits Number of bits in the mask
309 * @return The mask
310 */
cvmx_build_mask(u64 bits)311 static inline u64 cvmx_build_mask(u64 bits)
312 {
313 if (bits == 64)
314 return -1;
315
316 return ~((~0x0ull) << bits);
317 }
318
319 /**
320 * Extract bits out of a number
321 *
322 * @param input Number to extract from
323 * @param lsb Starting bit, least significant (0-63)
324 * @param width Width in bits (1-64)
325 *
326 * @return Extracted number
327 */
cvmx_bit_extract(u64 input,int lsb,int width)328 static inline u64 cvmx_bit_extract(u64 input, int lsb, int width)
329 {
330 u64 result = input >> lsb;
331
332 result &= cvmx_build_mask(width);
333
334 return result;
335 }
336
337 /**
338 * Perform mask and shift to place the supplied value into
339 * the supplied bit rage.
340 *
341 * Example: cvmx_build_bits(39,24,value)
342 * <pre>
343 * 6 5 4 3 3 2 1
344 * 3 5 7 9 1 3 5 7 0
345 * +-------+-------+-------+-------+-------+-------+-------+------+
346 * 000000000000000000000000___________value000000000000000000000000
347 * </pre>
348 *
349 * @param high_bit Highest bit value can occupy (inclusive) 0-63
350 * @param low_bit Lowest bit value can occupy inclusive 0-high_bit
351 * @param value Value to use
352 * @return Value masked and shifted
353 */
cvmx_build_bits(u64 high_bit,u64 low_bit,u64 value)354 static inline u64 cvmx_build_bits(u64 high_bit, u64 low_bit, u64 value)
355 {
356 return ((value & cvmx_build_mask(high_bit - low_bit + 1)) << low_bit);
357 }
358
cvmx_mask_to_localaddr(u64 addr)359 static inline u64 cvmx_mask_to_localaddr(u64 addr)
360 {
361 return (addr & 0xffffffffff);
362 }
363
cvmx_addr_on_node(u64 node,u64 addr)364 static inline u64 cvmx_addr_on_node(u64 node, u64 addr)
365 {
366 return (node << 40) | cvmx_mask_to_localaddr(addr);
367 }
368
cvmx_phys_to_ptr(u64 addr)369 static inline void *cvmx_phys_to_ptr(u64 addr)
370 {
371 return (void *)CKSEG0ADDR(addr);
372 }
373
cvmx_ptr_to_phys(void * ptr)374 static inline u64 cvmx_ptr_to_phys(void *ptr)
375 {
376 return virt_to_phys(ptr);
377 }
378
379 /**
380 * Number of the Core on which the program is currently running.
381 *
382 * @return core number
383 */
cvmx_get_core_num(void)384 static inline unsigned int cvmx_get_core_num(void)
385 {
386 unsigned int core_num;
387
388 CVMX_RDHWRNV(core_num, 0);
389 return core_num;
390 }
391
392 /**
393 * Node-local number of the core on which the program is currently running.
394 *
395 * @return core number on local node
396 */
cvmx_get_local_core_num(void)397 static inline unsigned int cvmx_get_local_core_num(void)
398 {
399 unsigned int core_num, core_mask;
400
401 CVMX_RDHWRNV(core_num, 0);
402 /* note that MAX_CORES may not be power of 2 */
403 core_mask = (1 << CVMX_NODE_NO_SHIFT) - 1;
404
405 return core_num & core_mask;
406 }
407
408 /**
409 * Returns the number of bits set in the provided value.
410 * Simple wrapper for POP instruction.
411 *
412 * @param val 32 bit value to count set bits in
413 *
414 * @return Number of bits set
415 */
cvmx_pop(u32 val)416 static inline u32 cvmx_pop(u32 val)
417 {
418 u32 pop;
419
420 CVMX_POP(pop, val);
421
422 return pop;
423 }
424
425 #define cvmx_read_csr_node(node, addr) csr_rd(addr)
426 #define cvmx_write_csr_node(node, addr, val) csr_wr(addr, val)
427
428 #define cvmx_printf printf
429 #define cvmx_vprintf vprintf
430
431 #if defined(DEBUG)
432 void cvmx_warn(const char *format, ...) __printf(1, 2);
433 #else
434 void cvmx_warn(const char *format, ...);
435 #endif
436
437 #define cvmx_warn_if(expression, format, ...) \
438 if (expression) \
439 cvmx_warn(format, ##__VA_ARGS__)
440
441 #endif /* __CVMX_REGS_H__ */
442