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