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