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