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