1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2015-2016 Freescale Semiconductor, Inc.
4 * Copyright 2017 NXP
5 */
6 #include <net/pfe_eth/pfe_eth.h>
7 #include <net/pfe_eth/pfe/pfe_hw.h>
8
9 static struct pe_info pe[MAX_PE];
10
11 /*
12 * Initializes the PFE library.
13 * Must be called before using any of the library functions.
14 */
pfe_lib_init(void)15 void pfe_lib_init(void)
16 {
17 int pfe_pe_id;
18
19 for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) {
20 pe[pfe_pe_id].dmem_base_addr =
21 (u32)CLASS_DMEM_BASE_ADDR(pfe_pe_id);
22 pe[pfe_pe_id].pmem_base_addr =
23 (u32)CLASS_IMEM_BASE_ADDR(pfe_pe_id);
24 pe[pfe_pe_id].pmem_size = (u32)CLASS_IMEM_SIZE;
25 pe[pfe_pe_id].mem_access_wdata =
26 (void *)CLASS_MEM_ACCESS_WDATA;
27 pe[pfe_pe_id].mem_access_addr = (void *)CLASS_MEM_ACCESS_ADDR;
28 pe[pfe_pe_id].mem_access_rdata = (void *)CLASS_MEM_ACCESS_RDATA;
29 }
30
31 for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) {
32 if (pfe_pe_id == TMU2_ID)
33 continue;
34 pe[pfe_pe_id].dmem_base_addr =
35 (u32)TMU_DMEM_BASE_ADDR(pfe_pe_id - TMU0_ID);
36 pe[pfe_pe_id].pmem_base_addr =
37 (u32)TMU_IMEM_BASE_ADDR(pfe_pe_id - TMU0_ID);
38 pe[pfe_pe_id].pmem_size = (u32)TMU_IMEM_SIZE;
39 pe[pfe_pe_id].mem_access_wdata = (void *)TMU_MEM_ACCESS_WDATA;
40 pe[pfe_pe_id].mem_access_addr = (void *)TMU_MEM_ACCESS_ADDR;
41 pe[pfe_pe_id].mem_access_rdata = (void *)TMU_MEM_ACCESS_RDATA;
42 }
43 }
44
45 /*
46 * Writes a buffer to PE internal memory from the host
47 * through indirect access registers.
48 *
49 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
50 * ..., UTIL_ID)
51 * @param[in] mem_access_addr DMEM destination address (must be 32bit
52 * aligned)
53 * @param[in] src Buffer source address
54 * @param[in] len Number of bytes to copy
55 */
pe_mem_memcpy_to32(int id,u32 mem_access_addr,const void * src,unsigned int len)56 static void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src,
57 unsigned int len)
58 {
59 u32 offset = 0, val, addr;
60 unsigned int len32 = len >> 2;
61 int i;
62
63 addr = mem_access_addr | PE_MEM_ACCESS_WRITE |
64 PE_MEM_ACCESS_BYTE_ENABLE(0, 4);
65
66 for (i = 0; i < len32; i++, offset += 4, src += 4) {
67 val = *(u32 *)src;
68 writel(cpu_to_be32(val), pe[id].mem_access_wdata);
69 writel(addr + offset, pe[id].mem_access_addr);
70 }
71
72 len = (len & 0x3);
73 if (len) {
74 val = 0;
75
76 addr = (mem_access_addr | PE_MEM_ACCESS_WRITE |
77 PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset;
78
79 for (i = 0; i < len; i++, src++)
80 val |= (*(u8 *)src) << (8 * i);
81
82 writel(cpu_to_be32(val), pe[id].mem_access_wdata);
83 writel(addr, pe[id].mem_access_addr);
84 }
85 }
86
87 /*
88 * Writes a buffer to PE internal data memory (DMEM) from the host
89 * through indirect access registers.
90 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
91 * ..., UTIL_ID)
92 * @param[in] dst DMEM destination address (must be 32bit
93 * aligned)
94 * @param[in] src Buffer source address
95 * @param[in] len Number of bytes to copy
96 */
pe_dmem_memcpy_to32(int id,u32 dst,const void * src,unsigned int len)97 static void pe_dmem_memcpy_to32(int id, u32 dst, const void *src,
98 unsigned int len)
99 {
100 pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | PE_MEM_ACCESS_DMEM,
101 src, len);
102 }
103
104 /*
105 * Writes a buffer to PE internal program memory (PMEM) from the host
106 * through indirect access registers.
107 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
108 * ..., TMU3_ID)
109 * @param[in] dst PMEM destination address (must be 32bit
110 * aligned)
111 * @param[in] src Buffer source address
112 * @param[in] len Number of bytes to copy
113 */
pe_pmem_memcpy_to32(int id,u32 dst,const void * src,unsigned int len)114 static void pe_pmem_memcpy_to32(int id, u32 dst, const void *src,
115 unsigned int len)
116 {
117 pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size
118 - 1)) | PE_MEM_ACCESS_IMEM, src, len);
119 }
120
121 /*
122 * Reads PE internal program memory (IMEM) from the host
123 * through indirect access registers.
124 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
125 * ..., TMU3_ID)
126 * @param[in] addr PMEM read address (must be aligned on size)
127 * @param[in] size Number of bytes to read (maximum 4, must not
128 * cross 32bit boundaries)
129 * @return the data read (in PE endianness, i.e BE).
130 */
pe_pmem_read(int id,u32 addr,u8 size)131 u32 pe_pmem_read(int id, u32 addr, u8 size)
132 {
133 u32 offset = addr & 0x3;
134 u32 mask = 0xffffffff >> ((4 - size) << 3);
135 u32 val;
136
137 addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1))
138 | PE_MEM_ACCESS_READ | PE_MEM_ACCESS_IMEM |
139 PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
140
141 writel(addr, pe[id].mem_access_addr);
142 val = be32_to_cpu(readl(pe[id].mem_access_rdata));
143
144 return (val >> (offset << 3)) & mask;
145 }
146
147 /*
148 * Writes PE internal data memory (DMEM) from the host
149 * through indirect access registers.
150 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
151 * ..., UTIL_ID)
152 * @param[in] val Value to write (in PE endianness, i.e BE)
153 * @param[in] addr DMEM write address (must be aligned on size)
154 * @param[in] size Number of bytes to write (maximum 4, must not
155 * cross 32bit boundaries)
156 */
pe_dmem_write(int id,u32 val,u32 addr,u8 size)157 void pe_dmem_write(int id, u32 val, u32 addr, u8 size)
158 {
159 u32 offset = addr & 0x3;
160
161 addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE |
162 PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
163
164 /* Indirect access interface is byte swapping data being written */
165 writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata);
166 writel(addr, pe[id].mem_access_addr);
167 }
168
169 /*
170 * Reads PE internal data memory (DMEM) from the host
171 * through indirect access registers.
172 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
173 * ..., UTIL_ID)
174 * @param[in] addr DMEM read address (must be aligned on size)
175 * @param[in] size Number of bytes to read (maximum 4, must not
176 * cross 32bit boundaries)
177 * @return the data read (in PE endianness, i.e BE).
178 */
pe_dmem_read(int id,u32 addr,u8 size)179 u32 pe_dmem_read(int id, u32 addr, u8 size)
180 {
181 u32 offset = addr & 0x3;
182 u32 mask = 0xffffffff >> ((4 - size) << 3);
183 u32 val;
184
185 addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_READ |
186 PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
187
188 writel(addr, pe[id].mem_access_addr);
189
190 /* Indirect access interface is byte swapping data being read */
191 val = be32_to_cpu(readl(pe[id].mem_access_rdata));
192
193 return (val >> (offset << 3)) & mask;
194 }
195
196 /*
197 * This function is used to write to CLASS internal bus peripherals (ccu,
198 * pe-lem) from the host
199 * through indirect access registers.
200 * @param[in] val value to write
201 * @param[in] addr Address to write to (must be aligned on size)
202 * @param[in] size Number of bytes to write (1, 2 or 4)
203 *
204 */
class_bus_write(u32 val,u32 addr,u8 size)205 static void class_bus_write(u32 val, u32 addr, u8 size)
206 {
207 u32 offset = addr & 0x3;
208
209 writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE);
210
211 addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE |
212 (size << 24);
213
214 writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA);
215 writel(addr, CLASS_BUS_ACCESS_ADDR);
216 }
217
218 /*
219 * Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host
220 * through indirect access registers.
221 * @param[in] addr Address to read from (must be aligned on size)
222 * @param[in] size Number of bytes to read (1, 2 or 4)
223 * @return the read data
224 */
class_bus_read(u32 addr,u8 size)225 static u32 class_bus_read(u32 addr, u8 size)
226 {
227 u32 offset = addr & 0x3;
228 u32 mask = 0xffffffff >> ((4 - size) << 3);
229 u32 val;
230
231 writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE);
232
233 addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24);
234
235 writel(addr, CLASS_BUS_ACCESS_ADDR);
236 val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA));
237
238 return (val >> (offset << 3)) & mask;
239 }
240
241 /*
242 * Writes data to the cluster memory (PE_LMEM)
243 * @param[in] dst PE LMEM destination address (must be 32bit aligned)
244 * @param[in] src Buffer source address
245 * @param[in] len Number of bytes to copy
246 */
class_pe_lmem_memcpy_to32(u32 dst,const void * src,unsigned int len)247 static void class_pe_lmem_memcpy_to32(u32 dst, const void *src,
248 unsigned int len)
249 {
250 u32 len32 = len >> 2;
251 int i;
252
253 for (i = 0; i < len32; i++, src += 4, dst += 4)
254 class_bus_write(*(u32 *)src, dst, 4);
255
256 if (len & 0x2) {
257 class_bus_write(*(u16 *)src, dst, 2);
258 src += 2;
259 dst += 2;
260 }
261
262 if (len & 0x1) {
263 class_bus_write(*(u8 *)src, dst, 1);
264 src++;
265 dst++;
266 }
267 }
268
269 /*
270 * Writes value to the cluster memory (PE_LMEM)
271 * @param[in] dst PE LMEM destination address (must be 32bit aligned)
272 * @param[in] val Value to write
273 * @param[in] len Number of bytes to write
274 */
class_pe_lmem_memset(u32 dst,int val,unsigned int len)275 static void class_pe_lmem_memset(u32 dst, int val, unsigned int len)
276 {
277 u32 len32 = len >> 2;
278 int i;
279
280 val = val | (val << 8) | (val << 16) | (val << 24);
281
282 for (i = 0; i < len32; i++, dst += 4)
283 class_bus_write(val, dst, 4);
284
285 if (len & 0x2) {
286 class_bus_write(val, dst, 2);
287 dst += 2;
288 }
289
290 if (len & 0x1) {
291 class_bus_write(val, dst, 1);
292 dst++;
293 }
294 }
295
296 /*
297 * Reads data from the cluster memory (PE_LMEM)
298 * @param[out] dst pointer to the source buffer data are copied to
299 * @param[in] len length in bytes of the amount of data to read
300 * from cluster memory
301 * @param[in] offset offset in bytes in the cluster memory where data are
302 * read from
303 */
pe_lmem_read(u32 * dst,u32 len,u32 offset)304 void pe_lmem_read(u32 *dst, u32 len, u32 offset)
305 {
306 u32 len32 = len >> 2;
307 int i = 0;
308
309 for (i = 0; i < len32; dst++, i++, offset += 4)
310 *dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, 4);
311
312 if (len & 0x03)
313 *dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, (len & 0x03));
314 }
315
316 /*
317 * Writes data to the cluster memory (PE_LMEM)
318 * @param[in] src pointer to the source buffer data are copied from
319 * @param[in] len length in bytes of the amount of data to write to the
320 * cluster memory
321 * @param[in] offset offset in bytes in the cluster memory where data are
322 * written to
323 */
pe_lmem_write(u32 * src,u32 len,u32 offset)324 void pe_lmem_write(u32 *src, u32 len, u32 offset)
325 {
326 u32 len32 = len >> 2;
327 int i = 0;
328
329 for (i = 0; i < len32; src++, i++, offset += 4)
330 class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, 4);
331
332 if (len & 0x03)
333 class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, (len &
334 0x03));
335 }
336
337 /*
338 * Loads an elf section into pmem
339 * Code needs to be at least 16bit aligned and only PROGBITS sections are
340 * supported
341 *
342 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ...,
343 * TMU3_ID)
344 * @param[in] data pointer to the elf firmware
345 * @param[in] shdr pointer to the elf section header
346 */
pe_load_pmem_section(int id,const void * data,Elf32_Shdr * shdr)347 static int pe_load_pmem_section(int id, const void *data, Elf32_Shdr *shdr)
348 {
349 u32 offset = be32_to_cpu(shdr->sh_offset);
350 u32 addr = be32_to_cpu(shdr->sh_addr);
351 u32 size = be32_to_cpu(shdr->sh_size);
352 u32 type = be32_to_cpu(shdr->sh_type);
353
354 if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
355 printf(
356 "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
357 __func__, addr, (unsigned long)data + offset);
358
359 return -1;
360 }
361
362 if (addr & 0x1) {
363 printf("%s: load address(%x) is not 16bit aligned\n",
364 __func__, addr);
365 return -1;
366 }
367
368 if (size & 0x1) {
369 printf("%s: load size(%x) is not 16bit aligned\n", __func__,
370 size);
371 return -1;
372 }
373
374 debug("pmem pe%d @%x len %d\n", id, addr, size);
375 switch (type) {
376 case SHT_PROGBITS:
377 pe_pmem_memcpy_to32(id, addr, data + offset, size);
378 break;
379
380 default:
381 printf("%s: unsupported section type(%x)\n", __func__, type);
382 return -1;
383 }
384
385 return 0;
386 }
387
388 /*
389 * Loads an elf section into dmem
390 * Data needs to be at least 32bit aligned, NOBITS sections are correctly
391 * initialized to 0
392 *
393 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
394 * ..., UTIL_ID)
395 * @param[in] data pointer to the elf firmware
396 * @param[in] shdr pointer to the elf section header
397 */
pe_load_dmem_section(int id,const void * data,Elf32_Shdr * shdr)398 static int pe_load_dmem_section(int id, const void *data, Elf32_Shdr *shdr)
399 {
400 u32 offset = be32_to_cpu(shdr->sh_offset);
401 u32 addr = be32_to_cpu(shdr->sh_addr);
402 u32 size = be32_to_cpu(shdr->sh_size);
403 u32 type = be32_to_cpu(shdr->sh_type);
404 u32 size32 = size >> 2;
405 int i;
406
407 if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
408 printf(
409 "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
410 __func__, addr, (unsigned long)data + offset);
411
412 return -1;
413 }
414
415 if (addr & 0x3) {
416 printf("%s: load address(%x) is not 32bit aligned\n",
417 __func__, addr);
418 return -1;
419 }
420
421 switch (type) {
422 case SHT_PROGBITS:
423 debug("dmem pe%d @%x len %d\n", id, addr, size);
424 pe_dmem_memcpy_to32(id, addr, data + offset, size);
425 break;
426
427 case SHT_NOBITS:
428 debug("dmem zero pe%d @%x len %d\n", id, addr, size);
429 for (i = 0; i < size32; i++, addr += 4)
430 pe_dmem_write(id, 0, addr, 4);
431
432 if (size & 0x3)
433 pe_dmem_write(id, 0, addr, size & 0x3);
434
435 break;
436
437 default:
438 printf("%s: unsupported section type(%x)\n", __func__, type);
439 return -1;
440 }
441
442 return 0;
443 }
444
445 /*
446 * Loads an elf section into DDR
447 * Data needs to be at least 32bit aligned, NOBITS sections are correctly
448 * initialized to 0
449 *
450 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
451 * ..., UTIL_ID)
452 * @param[in] data pointer to the elf firmware
453 * @param[in] shdr pointer to the elf section header
454 */
pe_load_ddr_section(int id,const void * data,Elf32_Shdr * shdr)455 static int pe_load_ddr_section(int id, const void *data, Elf32_Shdr *shdr)
456 {
457 u32 offset = be32_to_cpu(shdr->sh_offset);
458 u32 addr = be32_to_cpu(shdr->sh_addr);
459 u32 size = be32_to_cpu(shdr->sh_size);
460 u32 type = be32_to_cpu(shdr->sh_type);
461 u32 flags = be32_to_cpu(shdr->sh_flags);
462
463 switch (type) {
464 case SHT_PROGBITS:
465 debug("ddr pe%d @%x len %d\n", id, addr, size);
466 if (flags & SHF_EXECINSTR) {
467 if (id <= CLASS_MAX_ID) {
468 /* DO the loading only once in DDR */
469 if (id == CLASS0_ID) {
470 debug(
471 "%s: load address(%x) and elf file address(%lx) rcvd\n"
472 , __func__, addr,
473 (unsigned long)data + offset);
474 if (((unsigned long)(data + offset)
475 & 0x3) != (addr & 0x3)) {
476 printf(
477 "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
478 __func__, addr,
479 (unsigned long)data +
480 offset);
481
482 return -1;
483 }
484
485 if (addr & 0x1) {
486 printf(
487 "%s: load address(%x) is not 16bit aligned\n"
488 , __func__, addr);
489 return -1;
490 }
491
492 if (size & 0x1) {
493 printf(
494 "%s: load length(%x) is not 16bit aligned\n"
495 , __func__, size);
496 return -1;
497 }
498
499 memcpy((void *)DDR_PFE_TO_VIRT(addr),
500 data + offset, size);
501 }
502 } else {
503 printf(
504 "%s: unsupported ddr section type(%x) for PE(%d)\n"
505 , __func__, type, id);
506 return -1;
507 }
508
509 } else {
510 memcpy((void *)DDR_PFE_TO_VIRT(addr), data + offset,
511 size);
512 }
513
514 break;
515
516 case SHT_NOBITS:
517 debug("ddr zero pe%d @%x len %d\n", id, addr, size);
518 memset((void *)DDR_PFE_TO_VIRT(addr), 0, size);
519
520 break;
521
522 default:
523 printf("%s: unsupported section type(%x)\n", __func__, type);
524 return -1;
525 }
526
527 return 0;
528 }
529
530 /*
531 * Loads an elf section into pe lmem
532 * Data needs to be at least 32bit aligned, NOBITS sections are correctly
533 * initialized to 0
534 *
535 * @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID)
536 * @param[in] data pointer to the elf firmware
537 * @param[in] shdr pointer to the elf section header
538 */
pe_load_pe_lmem_section(int id,const void * data,Elf32_Shdr * shdr)539 static int pe_load_pe_lmem_section(int id, const void *data, Elf32_Shdr *shdr)
540 {
541 u32 offset = be32_to_cpu(shdr->sh_offset);
542 u32 addr = be32_to_cpu(shdr->sh_addr);
543 u32 size = be32_to_cpu(shdr->sh_size);
544 u32 type = be32_to_cpu(shdr->sh_type);
545
546 if (id > CLASS_MAX_ID) {
547 printf("%s: unsupported pe-lmem section type(%x) for PE(%d)\n",
548 __func__, type, id);
549 return -1;
550 }
551
552 if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
553 printf(
554 "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
555 __func__, addr, (unsigned long)data + offset);
556
557 return -1;
558 }
559
560 if (addr & 0x3) {
561 printf("%s: load address(%x) is not 32bit aligned\n",
562 __func__, addr);
563 return -1;
564 }
565
566 debug("lmem pe%d @%x len %d\n", id, addr, size);
567
568 switch (type) {
569 case SHT_PROGBITS:
570 class_pe_lmem_memcpy_to32(addr, data + offset, size);
571 break;
572
573 case SHT_NOBITS:
574 class_pe_lmem_memset(addr, 0, size);
575 break;
576
577 default:
578 printf("%s: unsupported section type(%x)\n", __func__, type);
579 return -1;
580 }
581
582 return 0;
583 }
584
585 /*
586 * Loads an elf section into a PE
587 * For now only supports loading a section to dmem (all PE's), pmem (class and
588 * tmu PE's), DDDR (util PE code)
589 * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
590 * ..., UTIL_ID)
591 * @param[in] data pointer to the elf firmware
592 * @param[in] shdr pointer to the elf section header
593 */
pe_load_elf_section(int id,const void * data,Elf32_Shdr * shdr)594 int pe_load_elf_section(int id, const void *data, Elf32_Shdr *shdr)
595 {
596 u32 addr = be32_to_cpu(shdr->sh_addr);
597 u32 size = be32_to_cpu(shdr->sh_size);
598
599 if (IS_DMEM(addr, size))
600 return pe_load_dmem_section(id, data, shdr);
601 else if (IS_PMEM(addr, size))
602 return pe_load_pmem_section(id, data, shdr);
603 else if (IS_PFE_LMEM(addr, size))
604 return 0;
605 else if (IS_PHYS_DDR(addr, size))
606 return pe_load_ddr_section(id, data, shdr);
607 else if (IS_PE_LMEM(addr, size))
608 return pe_load_pe_lmem_section(id, data, shdr);
609
610 printf("%s: unsupported memory range(%x)\n", __func__, addr);
611
612 return 0;
613 }
614
615 /**************************** BMU ***************************/
616 /*
617 * Resets a BMU block.
618 * @param[in] base BMU block base address
619 */
bmu_reset(void * base)620 static inline void bmu_reset(void *base)
621 {
622 writel(CORE_SW_RESET, base + BMU_CTRL);
623
624 /* Wait for self clear */
625 while (readl(base + BMU_CTRL) & CORE_SW_RESET)
626 ;
627 }
628
629 /*
630 * Enabled a BMU block.
631 * @param[in] base BMU block base address
632 */
bmu_enable(void * base)633 void bmu_enable(void *base)
634 {
635 writel(CORE_ENABLE, base + BMU_CTRL);
636 }
637
638 /*
639 * Disables a BMU block.
640 * @param[in] base BMU block base address
641 */
bmu_disable(void * base)642 static inline void bmu_disable(void *base)
643 {
644 writel(CORE_DISABLE, base + BMU_CTRL);
645 }
646
647 /*
648 * Sets the configuration of a BMU block.
649 * @param[in] base BMU block base address
650 * @param[in] cfg BMU configuration
651 */
bmu_set_config(void * base,struct bmu_cfg * cfg)652 static inline void bmu_set_config(void *base, struct bmu_cfg *cfg)
653 {
654 writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR);
655 writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG);
656 writel(cfg->size & 0xffff, base + BMU_BUF_SIZE);
657
658 /* Interrupts are never used */
659 writel(0x0, base + BMU_INT_ENABLE);
660 }
661
662 /*
663 * Initializes a BMU block.
664 * @param[in] base BMU block base address
665 * @param[in] cfg BMU configuration
666 */
bmu_init(void * base,struct bmu_cfg * cfg)667 void bmu_init(void *base, struct bmu_cfg *cfg)
668 {
669 bmu_disable(base);
670
671 bmu_set_config(base, cfg);
672
673 bmu_reset(base);
674 }
675
676 /**************************** GPI ***************************/
677 /*
678 * Resets a GPI block.
679 * @param[in] base GPI base address
680 */
gpi_reset(void * base)681 static inline void gpi_reset(void *base)
682 {
683 writel(CORE_SW_RESET, base + GPI_CTRL);
684 }
685
686 /*
687 * Enables a GPI block.
688 * @param[in] base GPI base address
689 */
gpi_enable(void * base)690 void gpi_enable(void *base)
691 {
692 writel(CORE_ENABLE, base + GPI_CTRL);
693 }
694
695 /*
696 * Disables a GPI block.
697 * @param[in] base GPI base address
698 */
gpi_disable(void * base)699 void gpi_disable(void *base)
700 {
701 writel(CORE_DISABLE, base + GPI_CTRL);
702 }
703
704 /*
705 * Sets the configuration of a GPI block.
706 * @param[in] base GPI base address
707 * @param[in] cfg GPI configuration
708 */
gpi_set_config(void * base,struct gpi_cfg * cfg)709 static inline void gpi_set_config(void *base, struct gpi_cfg *cfg)
710 {
711 writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base
712 + GPI_LMEM_ALLOC_ADDR);
713 writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base
714 + GPI_LMEM_FREE_ADDR);
715 writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base
716 + GPI_DDR_ALLOC_ADDR);
717 writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base
718 + GPI_DDR_FREE_ADDR);
719 writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR);
720 writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET);
721 writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET);
722 writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET);
723 writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET);
724 writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE);
725 writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE);
726
727 writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) |
728 GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG);
729 writel(cfg->tmlf_txthres, base + GPI_TMLF_TX);
730 writel(cfg->aseq_len, base + GPI_DTX_ASEQ);
731
732 /*Make GPI AXI transactions non-bufferable */
733 writel(0x1, base + GPI_AXI_CTRL);
734 }
735
736 /*
737 * Initializes a GPI block.
738 * @param[in] base GPI base address
739 * @param[in] cfg GPI configuration
740 */
gpi_init(void * base,struct gpi_cfg * cfg)741 void gpi_init(void *base, struct gpi_cfg *cfg)
742 {
743 gpi_reset(base);
744
745 gpi_disable(base);
746
747 gpi_set_config(base, cfg);
748 }
749
750 /**************************** CLASSIFIER ***************************/
751 /*
752 * Resets CLASSIFIER block.
753 */
class_reset(void)754 static inline void class_reset(void)
755 {
756 writel(CORE_SW_RESET, CLASS_TX_CTRL);
757 }
758
759 /*
760 * Enables all CLASS-PE's cores.
761 */
class_enable(void)762 void class_enable(void)
763 {
764 writel(CORE_ENABLE, CLASS_TX_CTRL);
765 }
766
767 /*
768 * Disables all CLASS-PE's cores.
769 */
class_disable(void)770 void class_disable(void)
771 {
772 writel(CORE_DISABLE, CLASS_TX_CTRL);
773 }
774
775 /*
776 * Sets the configuration of the CLASSIFIER block.
777 * @param[in] cfg CLASSIFIER configuration
778 */
class_set_config(struct class_cfg * cfg)779 static inline void class_set_config(struct class_cfg *cfg)
780 {
781 if (PLL_CLK_EN == 0) {
782 /* Clock ratio: for 1:1 the value is 0 */
783 writel(0x0, CLASS_PE_SYS_CLK_RATIO);
784 } else {
785 /* Clock ratio: for 1:2 the value is 1 */
786 writel(0x1, CLASS_PE_SYS_CLK_RATIO);
787 }
788 writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE);
789 writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE);
790 writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) |
791 CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits),
792 CLASS_ROUTE_HASH_ENTRY_SIZE);
793 writel(HASH_CRC_PORT_IP | QB2BUS_LE, CLASS_ROUTE_MULTI);
794
795 writel(cfg->route_table_baseaddr, CLASS_ROUTE_TABLE_BASE);
796 memset((void *)DDR_PFE_TO_VIRT(cfg->route_table_baseaddr), 0,
797 ROUTE_TABLE_SIZE);
798
799 writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0);
800 writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1);
801 writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0);
802 writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1);
803 writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR);
804
805 writel(23, CLASS_AFULL_THRES);
806 writel(23, CLASS_TSQ_FIFO_THRES);
807
808 writel(24, CLASS_MAX_BUF_CNT);
809 writel(24, CLASS_TSQ_MAX_CNT);
810
811 /*Make Class AXI transactions non-bufferable */
812 writel(0x1, CLASS_AXI_CTRL);
813
814 /*Make Util AXI transactions non-bufferable */
815 /*Util is disabled in U-boot, do it from here */
816 writel(0x1, UTIL_AXI_CTRL);
817 }
818
819 /*
820 * Initializes CLASSIFIER block.
821 * @param[in] cfg CLASSIFIER configuration
822 */
class_init(struct class_cfg * cfg)823 void class_init(struct class_cfg *cfg)
824 {
825 class_reset();
826
827 class_disable();
828
829 class_set_config(cfg);
830 }
831
832 /**************************** TMU ***************************/
833 /*
834 * Enables TMU-PE cores.
835 * @param[in] pe_mask TMU PE mask
836 */
tmu_enable(u32 pe_mask)837 void tmu_enable(u32 pe_mask)
838 {
839 writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL);
840 }
841
842 /*
843 * Disables TMU cores.
844 * @param[in] pe_mask TMU PE mask
845 */
tmu_disable(u32 pe_mask)846 void tmu_disable(u32 pe_mask)
847 {
848 writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL);
849 }
850
851 /*
852 * Initializes TMU block.
853 * @param[in] cfg TMU configuration
854 */
tmu_init(struct tmu_cfg * cfg)855 void tmu_init(struct tmu_cfg *cfg)
856 {
857 int q, phyno;
858
859 /* keep in soft reset */
860 writel(SW_RESET, TMU_CTRL);
861
862 /*Make Class AXI transactions non-bufferable */
863 writel(0x1, TMU_AXI_CTRL);
864
865 /* enable EMAC PHY ports */
866 writel(0x3, TMU_SYS_GENERIC_CONTROL);
867
868 writel(750, TMU_INQ_WATERMARK);
869
870 writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + GPI_INQ_PKTPTR),
871 TMU_PHY0_INQ_ADDR);
872 writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + GPI_INQ_PKTPTR),
873 TMU_PHY1_INQ_ADDR);
874
875 writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + GPI_INQ_PKTPTR),
876 TMU_PHY3_INQ_ADDR);
877 writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR);
878 writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR);
879 writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL),
880 TMU_BMU_INQ_ADDR);
881
882 /* enabling all 10 schedulers [9:0] of each TDQ */
883 writel(0x3FF, TMU_TDQ0_SCH_CTRL);
884 writel(0x3FF, TMU_TDQ1_SCH_CTRL);
885 writel(0x3FF, TMU_TDQ3_SCH_CTRL);
886
887 if (PLL_CLK_EN == 0) {
888 /* Clock ratio: for 1:1 the value is 0 */
889 writel(0x0, TMU_PE_SYS_CLK_RATIO);
890 } else {
891 /* Clock ratio: for 1:2 the value is 1 */
892 writel(0x1, TMU_PE_SYS_CLK_RATIO);
893 }
894
895 /* Extra packet pointers will be stored from this address onwards */
896 debug("TMU_LLM_BASE_ADDR %x\n", cfg->llm_base_addr);
897 writel(cfg->llm_base_addr, TMU_LLM_BASE_ADDR);
898
899 debug("TMU_LLM_QUE_LEN %x\n", cfg->llm_queue_len);
900 writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN);
901
902 writel(5, TMU_TDQ_IIFG_CFG);
903 writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE);
904
905 writel(0x0, TMU_CTRL);
906
907 /* MEM init */
908 writel(MEM_INIT, TMU_CTRL);
909
910 while (!(readl(TMU_CTRL) & MEM_INIT_DONE))
911 ;
912
913 /* LLM init */
914 writel(LLM_INIT, TMU_CTRL);
915
916 while (!(readl(TMU_CTRL) & LLM_INIT_DONE))
917 ;
918
919 /* set up each queue for tail drop */
920 for (phyno = 0; phyno < 4; phyno++) {
921 if (phyno == 2)
922 continue;
923 for (q = 0; q < 16; q++) {
924 u32 qmax;
925
926 writel((phyno << 8) | q, TMU_TEQ_CTRL);
927 writel(BIT(22), TMU_TEQ_QCFG);
928
929 if (phyno == 3)
930 qmax = DEFAULT_TMU3_QDEPTH;
931 else
932 qmax = (q == 0) ? DEFAULT_Q0_QDEPTH :
933 DEFAULT_MAX_QDEPTH;
934
935 writel(qmax << 18, TMU_TEQ_HW_PROB_CFG2);
936 writel(qmax >> 14, TMU_TEQ_HW_PROB_CFG3);
937 }
938 }
939 writel(0x05, TMU_TEQ_DISABLE_DROPCHK);
940 writel(0, TMU_CTRL);
941 }
942
943 /**************************** HIF ***************************/
944 /*
945 * Enable hif tx DMA and interrupt
946 */
hif_tx_enable(void)947 void hif_tx_enable(void)
948 {
949 writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL);
950 }
951
952 /*
953 * Disable hif tx DMA and interrupt
954 */
hif_tx_disable(void)955 void hif_tx_disable(void)
956 {
957 u32 hif_int;
958
959 writel(0, HIF_TX_CTRL);
960
961 hif_int = readl(HIF_INT_ENABLE);
962 hif_int &= HIF_TXPKT_INT_EN;
963 writel(hif_int, HIF_INT_ENABLE);
964 }
965
966 /*
967 * Enable hif rx DMA and interrupt
968 */
hif_rx_enable(void)969 void hif_rx_enable(void)
970 {
971 writel((HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
972 }
973
974 /*
975 * Disable hif rx DMA and interrupt
976 */
hif_rx_disable(void)977 void hif_rx_disable(void)
978 {
979 u32 hif_int;
980
981 writel(0, HIF_RX_CTRL);
982
983 hif_int = readl(HIF_INT_ENABLE);
984 hif_int &= HIF_RXPKT_INT_EN;
985 writel(hif_int, HIF_INT_ENABLE);
986 }
987
988 /*
989 * Initializes HIF copy block.
990 */
hif_init(void)991 void hif_init(void)
992 {
993 /* Initialize HIF registers */
994 writel(HIF_RX_POLL_CTRL_CYCLE << 16 | HIF_TX_POLL_CTRL_CYCLE,
995 HIF_POLL_CTRL);
996 /* Make HIF AXI transactions non-bufferable */
997 writel(0x1, HIF_AXI_CTRL);
998 }
999