1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/bug.h>
24#undef QBMAN_CCSR_TRACE
25#undef QBMAN_CINH_TRACE
26#undef QBMAN_CENA_TRACE
27
28
29
30
31
32#define QBMAN_CINH_ONLY
33
34static inline void word_copy(void *d, const void *s, unsigned int cnt)
35{
36 uint32_t *dd = d;
37 const uint32_t *ss = s;
38
39 while (cnt--)
40 *(dd++) = *(ss++);
41}
42
43
44
45
46
47
48static inline void u64_to_le32_copy(void *d, const uint64_t *s,
49 unsigned int cnt)
50{
51 uint32_t *dd = d;
52 const uint32_t *ss = (const uint32_t *)s;
53
54 while (cnt--) {
55
56
57
58
59#if defined(__BIG_ENDIAN)
60 *(dd++) = ss[1];
61 *(dd++) = ss[0];
62 ss += 2;
63#else
64 *(dd++) = *(ss++);
65 *(dd++) = *(ss++);
66#endif
67 }
68}
69static inline void u64_from_le32_copy(uint64_t *d, const void *s,
70 unsigned int cnt)
71{
72 const uint32_t *ss = s;
73 uint32_t *dd = (uint32_t *)d;
74
75 while (cnt--) {
76#if defined(__BIG_ENDIAN)
77 dd[1] = *(ss++);
78 dd[0] = *(ss++);
79 dd += 2;
80#else
81 *(dd++) = *(ss++);
82 *(dd++) = *(ss++);
83#endif
84 }
85}
86
87
88#if defined(__BIG_ENDIAN)
89static inline uint32_t make_le32(uint32_t val)
90{
91 return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
92 ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
93}
94#else
95#define make_le32(val) (val)
96#endif
97static inline void make_le32_n(uint32_t *val, unsigned int num)
98{
99 while (num--) {
100 *val = make_le32(*val);
101 val++;
102 }
103}
104
105
106
107
108struct qbman_swp_sys {
109
110
111
112
113
114
115 void *cena;
116 void __iomem *addr_cena;
117 void __iomem *addr_cinh;
118};
119
120
121
122
123
124
125
126
127
128static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset,
129 uint32_t val)
130{
131 __raw_writel(val, s->addr_cinh + offset);
132#ifdef QBMAN_CINH_TRACE
133 pr_info("qbman_cinh_write(%p:0x%03x) 0x%08x\n",
134 s->addr_cinh, offset, val);
135#endif
136}
137
138static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset)
139{
140 uint32_t reg = __raw_readl(s->addr_cinh + offset);
141
142#ifdef QBMAN_CINH_TRACE
143 pr_info("qbman_cinh_read(%p:0x%03x) 0x%08x\n",
144 s->addr_cinh, offset, reg);
145#endif
146 return reg;
147}
148
149static inline void *qbman_cena_write_start(struct qbman_swp_sys *s,
150 uint32_t offset)
151{
152 void *shadow = s->cena + offset;
153
154#ifdef QBMAN_CENA_TRACE
155 pr_info("qbman_cena_write_start(%p:0x%03x) %p\n",
156 s->addr_cena, offset, shadow);
157#endif
158 BUG_ON(offset & 63);
159 dcbz(shadow);
160 return shadow;
161}
162
163static inline void qbman_cena_write_complete(struct qbman_swp_sys *s,
164 uint32_t offset, void *cmd)
165{
166 const uint32_t *shadow = cmd;
167 int loop;
168
169#ifdef QBMAN_CENA_TRACE
170 pr_info("qbman_cena_write_complete(%p:0x%03x) %p\n",
171 s->addr_cena, offset, shadow);
172 hexdump(cmd, 64);
173#endif
174 for (loop = 15; loop >= 0; loop--)
175#ifdef QBMAN_CINH_ONLY
176 __raw_writel(shadow[loop], s->addr_cinh +
177 offset + loop * 4);
178#else
179 __raw_writel(shadow[loop], s->addr_cena +
180 offset + loop * 4);
181#endif
182}
183
184static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset)
185{
186 uint32_t *shadow = s->cena + offset;
187 unsigned int loop;
188
189#ifdef QBMAN_CENA_TRACE
190 pr_info("qbman_cena_read(%p:0x%03x) %p\n",
191 s->addr_cena, offset, shadow);
192#endif
193
194 for (loop = 0; loop < 16; loop++)
195#ifdef QBMAN_CINH_ONLY
196 shadow[loop] = __raw_readl(s->addr_cinh + offset
197 + loop * 4);
198#else
199 shadow[loop] = __raw_readl(s->addr_cena + offset
200 + loop * 4);
201#endif
202#ifdef QBMAN_CENA_TRACE
203 hexdump(shadow, 64);
204#endif
205 return shadow;
206}
207
208static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s,
209 uint32_t offset)
210{
211}
212
213
214
215
216
217
218
219
220#define QBMAN_CINH_SWP_CFG 0xd00
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn,
236 uint8_t est, uint8_t rpm, uint8_t dcm,
237 uint8_t epm, int sd, int sp, int se,
238 int dp, int de, int ep)
239{
240 uint32_t reg;
241
242 reg = e32_uint8_t(20, (uint32_t)(3 + (max_fill >> 3)), max_fill) |
243 e32_uint8_t(16, 3, est) | e32_uint8_t(12, 2, rpm) |
244 e32_uint8_t(10, 2, dcm) | e32_uint8_t(8, 2, epm) |
245 e32_int(5, 1, sd) | e32_int(4, 1, sp) | e32_int(3, 1, se) |
246 e32_int(2, 1, dp) | e32_int(1, 1, de) | e32_int(0, 1, ep) |
247 e32_uint8_t(14, 1, wn);
248 return reg;
249}
250
251static inline int qbman_swp_sys_init(struct qbman_swp_sys *s,
252 const struct qbman_swp_desc *d,
253 uint8_t dqrr_size)
254{
255 uint32_t reg;
256
257 s->addr_cena = d->cena_bar;
258 s->addr_cinh = d->cinh_bar;
259 s->cena = (void *)valloc(CONFIG_SYS_PAGE_SIZE);
260 if (!s->cena) {
261 printf("Could not allocate page for cena shadow\n");
262 return -1;
263 }
264 memset((void *)s->cena, 0x00, CONFIG_SYS_PAGE_SIZE);
265
266#ifdef QBMAN_CHECKING
267
268
269
270
271 reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
272 BUG_ON(reg);
273#endif
274#ifdef QBMAN_CINH_ONLY
275 reg = qbman_set_swp_cfg(dqrr_size, 1, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
276#else
277 reg = qbman_set_swp_cfg(dqrr_size, 0, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
278#endif
279 qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg);
280 reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
281 if (!reg) {
282 printf("The portal is not enabled!\n");
283 free(s->cena);
284 return -1;
285 }
286 return 0;
287}
288
289static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s)
290{
291 free((void *)s->cena);
292}
293