1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2009-2011 Freescale Semiconductor, Inc. 4 * Dave Liu <daveliu@freescale.com> 5 */ 6 #include <common.h> 7 #include <malloc.h> 8 #include <asm/io.h> 9 #include <linux/errno.h> 10 11 #include "fm.h" 12 #include <fsl_qe.h> /* For struct qe_firmware */ 13 14 #ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND 15 #include <nand.h> 16 #elif defined(CONFIG_SYS_QE_FW_IN_SPIFLASH) 17 #include <spi_flash.h> 18 #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_MMC) 19 #include <mmc.h> 20 #endif 21 22 struct fm_muram muram[CONFIG_SYS_NUM_FMAN]; 23 24 void *fm_muram_base(int fm_idx) 25 { 26 return muram[fm_idx].base; 27 } 28 29 void *fm_muram_alloc(int fm_idx, size_t size, ulong align) 30 { 31 void *ret; 32 ulong align_mask; 33 size_t off; 34 void *save; 35 36 align_mask = align - 1; 37 save = muram[fm_idx].alloc; 38 39 off = (ulong)save & align_mask; 40 if (off != 0) 41 muram[fm_idx].alloc += (align - off); 42 off = size & align_mask; 43 if (off != 0) 44 size += (align - off); 45 if ((muram[fm_idx].alloc + size) >= muram[fm_idx].top) { 46 muram[fm_idx].alloc = save; 47 printf("%s: run out of ram.\n", __func__); 48 return NULL; 49 } 50 51 ret = muram[fm_idx].alloc; 52 muram[fm_idx].alloc += size; 53 memset((void *)ret, 0, size); 54 55 return ret; 56 } 57 58 static void fm_init_muram(int fm_idx, void *reg) 59 { 60 void *base = reg; 61 62 muram[fm_idx].base = base; 63 muram[fm_idx].size = CONFIG_SYS_FM_MURAM_SIZE; 64 muram[fm_idx].alloc = base + FM_MURAM_RES_SIZE; 65 muram[fm_idx].top = base + CONFIG_SYS_FM_MURAM_SIZE; 66 } 67 68 /* 69 * fm_upload_ucode - Fman microcode upload worker function 70 * 71 * This function does the actual uploading of an Fman microcode 72 * to an Fman. 73 */ 74 static void fm_upload_ucode(int fm_idx, struct fm_imem *imem, 75 u32 *ucode, unsigned int size) 76 { 77 unsigned int i; 78 unsigned int timeout = 1000000; 79 80 /* enable address auto increase */ 81 out_be32(&imem->iadd, IRAM_IADD_AIE); 82 /* write microcode to IRAM */ 83 for (i = 0; i < size / 4; i++) 84 out_be32(&imem->idata, (be32_to_cpu(ucode[i]))); 85 86 /* verify if the writing is over */ 87 out_be32(&imem->iadd, 0); 88 while ((in_be32(&imem->idata) != be32_to_cpu(ucode[0])) && --timeout) 89 ; 90 if (!timeout) 91 printf("Fman%u: microcode upload timeout\n", fm_idx + 1); 92 93 /* enable microcode from IRAM */ 94 out_be32(&imem->iready, IRAM_READY); 95 } 96 97 /* 98 * Upload an Fman firmware 99 * 100 * This function is similar to qe_upload_firmware(), exception that it uploads 101 * a microcode to the Fman instead of the QE. 102 * 103 * Because the process for uploading a microcode to the Fman is similar for 104 * that of the QE, the QE firmware binary format is used for Fman microcode. 105 * It should be possible to unify these two functions, but for now we keep them 106 * separate. 107 */ 108 static int fman_upload_firmware(int fm_idx, 109 struct fm_imem *fm_imem, 110 const struct qe_firmware *firmware) 111 { 112 unsigned int i; 113 u32 crc; 114 size_t calc_size = sizeof(struct qe_firmware); 115 size_t length; 116 const struct qe_header *hdr; 117 118 if (!firmware) { 119 printf("Fman%u: Invalid address for firmware\n", fm_idx + 1); 120 return -EINVAL; 121 } 122 123 hdr = &firmware->header; 124 length = be32_to_cpu(hdr->length); 125 126 /* Check the magic */ 127 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 128 (hdr->magic[2] != 'F')) { 129 printf("Fman%u: Data at %p is not a firmware\n", fm_idx + 1, 130 firmware); 131 return -EPERM; 132 } 133 134 /* Check the version */ 135 if (hdr->version != 1) { 136 printf("Fman%u: Unsupported firmware version %u\n", fm_idx + 1, 137 hdr->version); 138 return -EPERM; 139 } 140 141 /* Validate some of the fields */ 142 if ((firmware->count != 1)) { 143 printf("Fman%u: Invalid data in firmware header\n", fm_idx + 1); 144 return -EINVAL; 145 } 146 147 /* Validate the length and check if there's a CRC */ 148 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); 149 150 for (i = 0; i < firmware->count; i++) 151 /* 152 * For situations where the second RISC uses the same microcode 153 * as the first, the 'code_offset' and 'count' fields will be 154 * zero, so it's okay to add those. 155 */ 156 calc_size += sizeof(u32) * 157 be32_to_cpu(firmware->microcode[i].count); 158 159 /* Validate the length */ 160 if (length != calc_size + sizeof(u32)) { 161 printf("Fman%u: Invalid length in firmware header\n", 162 fm_idx + 1); 163 return -EPERM; 164 } 165 166 /* 167 * Validate the CRC. We would normally call crc32_no_comp(), but that 168 * function isn't available unless you turn on JFFS support. 169 */ 170 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size)); 171 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) { 172 printf("Fman%u: Firmware CRC is invalid\n", fm_idx + 1); 173 return -EIO; 174 } 175 176 /* Loop through each microcode. */ 177 for (i = 0; i < firmware->count; i++) { 178 const struct qe_microcode *ucode = &firmware->microcode[i]; 179 180 /* Upload a microcode if it's present */ 181 if (be32_to_cpu(ucode->code_offset)) { 182 u32 ucode_size; 183 u32 *code; 184 printf("Fman%u: Uploading microcode version %u.%u.%u\n", 185 fm_idx + 1, ucode->major, ucode->minor, 186 ucode->revision); 187 code = (void *)firmware + 188 be32_to_cpu(ucode->code_offset); 189 ucode_size = sizeof(u32) * be32_to_cpu(ucode->count); 190 fm_upload_ucode(fm_idx, fm_imem, code, ucode_size); 191 } 192 } 193 194 return 0; 195 } 196 197 static u32 fm_assign_risc(int port_id) 198 { 199 u32 risc_sel, val; 200 risc_sel = (port_id & 0x1) ? FMFPPRC_RISC2 : FMFPPRC_RISC1; 201 val = (port_id << FMFPPRC_PORTID_SHIFT) & FMFPPRC_PORTID_MASK; 202 val |= ((risc_sel << FMFPPRC_ORA_SHIFT) | risc_sel); 203 204 return val; 205 } 206 207 static void fm_init_fpm(struct fm_fpm *fpm) 208 { 209 int i, port_id; 210 u32 val; 211 212 setbits_be32(&fpm->fmfpee, FMFPEE_EHM | FMFPEE_UEC | 213 FMFPEE_CER | FMFPEE_DER); 214 215 /* IM mode, each even port ID to RISC#1, each odd port ID to RISC#2 */ 216 217 /* offline/parser port */ 218 for (i = 0; i < MAX_NUM_OH_PORT; i++) { 219 port_id = OH_PORT_ID_BASE + i; 220 val = fm_assign_risc(port_id); 221 out_be32(&fpm->fpmprc, val); 222 } 223 /* Rx 1G port */ 224 for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) { 225 port_id = RX_PORT_1G_BASE + i; 226 val = fm_assign_risc(port_id); 227 out_be32(&fpm->fpmprc, val); 228 } 229 /* Tx 1G port */ 230 for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) { 231 port_id = TX_PORT_1G_BASE + i; 232 val = fm_assign_risc(port_id); 233 out_be32(&fpm->fpmprc, val); 234 } 235 /* Rx 10G port */ 236 port_id = RX_PORT_10G_BASE; 237 val = fm_assign_risc(port_id); 238 out_be32(&fpm->fpmprc, val); 239 /* Tx 10G port */ 240 port_id = TX_PORT_10G_BASE; 241 val = fm_assign_risc(port_id); 242 out_be32(&fpm->fpmprc, val); 243 244 /* disable the dispatch limit in IM case */ 245 out_be32(&fpm->fpmflc, FMFP_FLC_DISP_LIM_NONE); 246 /* clear events */ 247 out_be32(&fpm->fmfpee, FMFPEE_CLEAR_EVENT); 248 249 /* clear risc events */ 250 for (i = 0; i < 4; i++) 251 out_be32(&fpm->fpmcev[i], 0xffffffff); 252 253 /* clear error */ 254 out_be32(&fpm->fpmrcr, FMFP_RCR_MDEC | FMFP_RCR_IDEC); 255 } 256 257 static int fm_init_bmi(int fm_idx, struct fm_bmi_common *bmi) 258 { 259 int blk, i, port_id; 260 u32 val; 261 size_t offset; 262 void *base; 263 264 /* alloc free buffer pool in MURAM */ 265 base = fm_muram_alloc(fm_idx, FM_FREE_POOL_SIZE, FM_FREE_POOL_ALIGN); 266 if (!base) { 267 printf("%s: no muram for free buffer pool\n", __func__); 268 return -ENOMEM; 269 } 270 offset = base - fm_muram_base(fm_idx); 271 272 /* Need 128KB total free buffer pool size */ 273 val = offset / 256; 274 blk = FM_FREE_POOL_SIZE / 256; 275 /* in IM, we must not begin from offset 0 in MURAM */ 276 val |= ((blk - 1) << FMBM_CFG1_FBPS_SHIFT); 277 out_be32(&bmi->fmbm_cfg1, val); 278 279 /* disable all BMI interrupt */ 280 out_be32(&bmi->fmbm_ier, FMBM_IER_DISABLE_ALL); 281 282 /* clear all events */ 283 out_be32(&bmi->fmbm_ievr, FMBM_IEVR_CLEAR_ALL); 284 285 /* 286 * set port parameters - FMBM_PP_x 287 * max tasks 10G Rx/Tx=12, 1G Rx/Tx 4, others is 1 288 * max dma 10G Rx/Tx=3, others is 1 289 * set port FIFO size - FMBM_PFS_x 290 * 4KB for all Rx and Tx ports 291 */ 292 /* offline/parser port */ 293 for (i = 0; i < MAX_NUM_OH_PORT; i++) { 294 port_id = OH_PORT_ID_BASE + i - 1; 295 /* max tasks=1, max dma=1, no extra */ 296 out_be32(&bmi->fmbm_pp[port_id], 0); 297 /* port FIFO size - 256 bytes, no extra */ 298 out_be32(&bmi->fmbm_pfs[port_id], 0); 299 } 300 /* Rx 1G port */ 301 for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) { 302 port_id = RX_PORT_1G_BASE + i - 1; 303 /* max tasks=4, max dma=1, no extra */ 304 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(4)); 305 /* FIFO size - 4KB, no extra */ 306 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf)); 307 } 308 /* Tx 1G port FIFO size - 4KB, no extra */ 309 for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) { 310 port_id = TX_PORT_1G_BASE + i - 1; 311 /* max tasks=4, max dma=1, no extra */ 312 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(4)); 313 /* FIFO size - 4KB, no extra */ 314 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf)); 315 } 316 /* Rx 10G port */ 317 port_id = RX_PORT_10G_BASE - 1; 318 /* max tasks=12, max dma=3, no extra */ 319 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(12) | FMBM_PP_MXD(3)); 320 /* FIFO size - 4KB, no extra */ 321 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf)); 322 323 /* Tx 10G port */ 324 port_id = TX_PORT_10G_BASE - 1; 325 /* max tasks=12, max dma=3, no extra */ 326 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(12) | FMBM_PP_MXD(3)); 327 /* FIFO size - 4KB, no extra */ 328 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf)); 329 330 /* initialize internal buffers data base (linked list) */ 331 out_be32(&bmi->fmbm_init, FMBM_INIT_START); 332 333 return 0; 334 } 335 336 static void fm_init_qmi(struct fm_qmi_common *qmi) 337 { 338 /* disable all error interrupts */ 339 out_be32(&qmi->fmqm_eien, FMQM_EIEN_DISABLE_ALL); 340 /* clear all error events */ 341 out_be32(&qmi->fmqm_eie, FMQM_EIE_CLEAR_ALL); 342 343 /* disable all interrupts */ 344 out_be32(&qmi->fmqm_ien, FMQM_IEN_DISABLE_ALL); 345 /* clear all interrupts */ 346 out_be32(&qmi->fmqm_ie, FMQM_IE_CLEAR_ALL); 347 } 348 349 /* Init common part of FM, index is fm num# like fm as above */ 350 int fm_init_common(int index, struct ccsr_fman *reg) 351 { 352 int rc; 353 #if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) 354 void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR; 355 #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND) 356 size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH; 357 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); 358 359 rc = nand_read(get_nand_dev_by_index(0), 360 (loff_t)CONFIG_SYS_FMAN_FW_ADDR, 361 &fw_length, (u_char *)addr); 362 if (rc == -EUCLEAN) { 363 printf("NAND read of FMAN firmware at offset 0x%x failed %d\n", 364 CONFIG_SYS_FMAN_FW_ADDR, rc); 365 } 366 #elif defined(CONFIG_SYS_QE_FW_IN_SPIFLASH) 367 struct spi_flash *ucode_flash; 368 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); 369 int ret = 0; 370 371 #ifdef CONFIG_DM_SPI_FLASH 372 struct udevice *new; 373 374 /* speed and mode will be read from DT */ 375 ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, 376 0, 0, &new); 377 378 ucode_flash = dev_get_uclass_priv(new); 379 #else 380 ucode_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, 381 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); 382 #endif 383 if (!ucode_flash) 384 printf("SF: probe for ucode failed\n"); 385 else { 386 ret = spi_flash_read(ucode_flash, CONFIG_SYS_FMAN_FW_ADDR, 387 CONFIG_SYS_QE_FMAN_FW_LENGTH, addr); 388 if (ret) 389 printf("SF: read for ucode failed\n"); 390 spi_flash_free(ucode_flash); 391 } 392 #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_MMC) 393 int dev = CONFIG_SYS_MMC_ENV_DEV; 394 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); 395 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512; 396 u32 blk = CONFIG_SYS_FMAN_FW_ADDR / 512; 397 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); 398 399 if (!mmc) 400 printf("\nMMC cannot find device for ucode\n"); 401 else { 402 printf("\nMMC read: dev # %u, block # %u, count %u ...\n", 403 dev, blk, cnt); 404 mmc_init(mmc); 405 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt, 406 addr); 407 } 408 #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_REMOTE) 409 void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR; 410 #else 411 void *addr = NULL; 412 #endif 413 414 /* Upload the Fman microcode if it's present */ 415 rc = fman_upload_firmware(index, ®->fm_imem, addr); 416 if (rc) 417 return rc; 418 env_set_addr("fman_ucode", addr); 419 420 fm_init_muram(index, ®->muram); 421 fm_init_qmi(®->fm_qmi_common); 422 fm_init_fpm(®->fm_fpm); 423 424 /* clear DMA status */ 425 setbits_be32(®->fm_dma.fmdmsr, FMDMSR_CLEAR_ALL); 426 427 /* set DMA mode */ 428 setbits_be32(®->fm_dma.fmdmmr, FMDMMR_SBER); 429 430 return fm_init_bmi(index, ®->fm_bmi_common); 431 } 432