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