]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
a2a55e51 PK |
2 | /* |
3 | * Copyright (C) 2014 Freescale Semiconductor | |
a2a55e51 PK |
4 | */ |
5 | ||
6 | /* Perform extra checking */ | |
7 | #include <common.h> | |
8 | #include <errno.h> | |
9 | #include <asm/io.h> | |
10 | #include <linux/types.h> | |
cd8aefc0 | 11 | #include <asm/atomic.h> |
a2a55e51 | 12 | #include <malloc.h> |
8e62f1ee | 13 | #include <asm/arch/soc.h> |
a2a55e51 PK |
14 | #include <fsl-mc/fsl_qbman_base.h> |
15 | ||
16 | #define QBMAN_CHECKING | |
17 | ||
18 | /* Any time there is a register interface which we poll on, this provides a | |
19 | * "break after x iterations" scheme for it. It's handy for debugging, eg. | |
20 | * where you don't want millions of lines of log output from a polling loop | |
21 | * that won't, because such things tend to drown out the earlier log output | |
22 | * that might explain what caused the problem. (NB: put ";" after each macro!) | |
23 | * TODO: we should probably remove this once we're done sanitising the | |
24 | * simulator... | |
25 | */ | |
26 | #define DBG_POLL_START(loopvar) (loopvar = 10) | |
27 | #define DBG_POLL_CHECK(loopvar) \ | |
28 | do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0) | |
29 | ||
30 | /* For CCSR or portal-CINH registers that contain fields at arbitrary offsets | |
31 | * and widths, these macro-generated encode/decode/isolate/remove inlines can | |
32 | * be used. | |
33 | * | |
34 | * Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type), | |
35 | * where the field is located 3 bits "up" from the least-significant bit of the | |
36 | * register (ie. the field location within the 32-bit register corresponds to a | |
37 | * mask of 0x0001fff8), you would do; | |
38 | * uint16_t field = d32_uint16_t(3, 14, reg_value); | |
39 | * | |
40 | * Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE, | |
41 | * non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!" | |
42 | * operator) into a register at bit location 0x00080000 (19 bits "in" from the | |
43 | * LS bit), do; | |
44 | * reg_value |= e32_int(19, 1, !!field); | |
45 | * | |
46 | * If you wish to read-modify-write a register, such that you leave the 14-bit | |
47 | * field as-is but have all other fields set to zero, then "i"solate the 14-bit | |
48 | * value using; | |
49 | * reg_value = i32_uint16_t(3, 14, reg_value); | |
50 | * | |
51 | * Alternatively, you could "r"emove the 1-bit boolean field (setting it to | |
52 | * zero) but leaving all other fields as-is; | |
53 | * reg_val = r32_int(19, 1, reg_value); | |
54 | * | |
55 | */ | |
56 | #define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \ | |
57 | (uint32_t)((1 << width) - 1)) | |
58 | #define DECLARE_CODEC32(t) \ | |
59 | static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \ | |
60 | { \ | |
61 | BUG_ON(width > (sizeof(t) * 8)); \ | |
62 | return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \ | |
63 | } \ | |
64 | static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \ | |
65 | { \ | |
66 | BUG_ON(width > (sizeof(t) * 8)); \ | |
67 | return (t)((val >> lsoffset) & MAKE_MASK32(width)); \ | |
68 | } \ | |
69 | static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \ | |
70 | uint32_t val) \ | |
71 | { \ | |
72 | BUG_ON(width > (sizeof(t) * 8)); \ | |
73 | return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \ | |
74 | } \ | |
75 | static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \ | |
76 | uint32_t val) \ | |
77 | { \ | |
78 | BUG_ON(width > (sizeof(t) * 8)); \ | |
79 | return ~(MAKE_MASK32(width) << lsoffset) & val; \ | |
80 | } | |
81 | DECLARE_CODEC32(uint32_t) | |
82 | DECLARE_CODEC32(uint16_t) | |
83 | DECLARE_CODEC32(uint8_t) | |
84 | DECLARE_CODEC32(int) | |
85 | ||
86 | /*********************/ | |
87 | /* Debugging assists */ | |
88 | /*********************/ | |
89 | ||
90 | static inline void __hexdump(unsigned long start, unsigned long end, | |
91 | unsigned long p, size_t sz, const unsigned char *c) | |
92 | { | |
93 | while (start < end) { | |
94 | unsigned int pos = 0; | |
95 | char buf[64]; | |
96 | int nl = 0; | |
97 | ||
98 | pos += sprintf(buf + pos, "%08lx: ", start); | |
99 | do { | |
100 | if ((start < p) || (start >= (p + sz))) | |
101 | pos += sprintf(buf + pos, ".."); | |
102 | else | |
103 | pos += sprintf(buf + pos, "%02x", *(c++)); | |
104 | if (!(++start & 15)) { | |
105 | buf[pos++] = '\n'; | |
106 | nl = 1; | |
107 | } else { | |
108 | nl = 0; | |
109 | if (!(start & 1)) | |
110 | buf[pos++] = ' '; | |
111 | if (!(start & 3)) | |
112 | buf[pos++] = ' '; | |
113 | } | |
114 | } while (start & 15); | |
115 | if (!nl) | |
116 | buf[pos++] = '\n'; | |
117 | buf[pos] = '\0'; | |
118 | debug("%s", buf); | |
119 | } | |
120 | } | |
121 | static inline void hexdump(const void *ptr, size_t sz) | |
122 | { | |
123 | unsigned long p = (unsigned long)ptr; | |
124 | unsigned long start = p & ~(unsigned long)15; | |
125 | unsigned long end = (p + sz + 15) & ~(unsigned long)15; | |
126 | const unsigned char *c = ptr; | |
127 | ||
128 | __hexdump(start, end, p, sz, c); | |
129 | } | |
130 | ||
131 | #if defined(__BIG_ENDIAN) | |
132 | #define DQRR_TOK_OFFSET 0 | |
133 | #else | |
134 | #define DQRR_TOK_OFFSET 24 | |
135 | #endif | |
136 | ||
137 | /* Similarly-named functions */ | |
138 | #define upper32(a) upper_32_bits(a) | |
139 | #define lower32(a) lower_32_bits(a) | |
140 | ||
141 | /****************/ | |
142 | /* arch assists */ | |
143 | /****************/ | |
144 | ||
145 | static inline void dcbz(void *ptr) | |
146 | { | |
147 | uint32_t *p = ptr; | |
148 | BUG_ON((unsigned long)ptr & 63); | |
149 | p[0] = 0; | |
150 | p[1] = 0; | |
151 | p[2] = 0; | |
152 | p[3] = 0; | |
153 | p[4] = 0; | |
154 | p[5] = 0; | |
155 | p[6] = 0; | |
156 | p[7] = 0; | |
157 | p[8] = 0; | |
158 | p[9] = 0; | |
159 | p[10] = 0; | |
160 | p[11] = 0; | |
161 | p[12] = 0; | |
162 | p[13] = 0; | |
163 | p[14] = 0; | |
164 | p[15] = 0; | |
165 | } | |
166 | ||
167 | #define lwsync() | |
168 | ||
8e62f1ee PJ |
169 | void qbman_version(u32 *major, u32 *minor) |
170 | { | |
171 | u32 svr_dev_id; | |
172 | ||
173 | /* | |
174 | * LS2080A SoC and its personalities has qbman cotroller version 4.0 | |
175 | * New SoCs like LS2088A, LS1088A has qbman conroller version 4.1 | |
176 | */ | |
a8f33034 W |
177 | svr_dev_id = get_svr(); |
178 | if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A))) { | |
8e62f1ee PJ |
179 | *major = 4; |
180 | *minor = 0; | |
181 | } else { | |
182 | *major = 4; | |
183 | *minor = 1; | |
184 | } | |
185 | } | |
186 | ||
a2a55e51 | 187 | #include "qbman_sys.h" |