linux/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Marvell RPM CN10K driver
   3 *
   4 * Copyright (C) 2020 Marvell.
   5 */
   6
   7#include <linux/bitfield.h>
   8#include <linux/pci.h>
   9#include "rvu.h"
  10#include "cgx.h"
  11#include "rvu_reg.h"
  12
  13/* RVU LMTST */
  14#define LMT_TBL_OP_READ         0
  15#define LMT_TBL_OP_WRITE        1
  16#define LMT_MAP_TABLE_SIZE      (128 * 1024)
  17#define LMT_MAPTBL_ENTRY_SIZE   16
  18
  19/* Function to perform operations (read/write) on lmtst map table */
  20static int lmtst_map_table_ops(struct rvu *rvu, u32 index, u64 *val,
  21                               int lmt_tbl_op)
  22{
  23        void __iomem *lmt_map_base;
  24        u64 tbl_base;
  25
  26        tbl_base = rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_MAP_BASE);
  27
  28        lmt_map_base = ioremap_wc(tbl_base, LMT_MAP_TABLE_SIZE);
  29        if (!lmt_map_base) {
  30                dev_err(rvu->dev, "Failed to setup lmt map table mapping!!\n");
  31                return -ENOMEM;
  32        }
  33
  34        if (lmt_tbl_op == LMT_TBL_OP_READ) {
  35                *val = readq(lmt_map_base + index);
  36        } else {
  37                writeq((*val), (lmt_map_base + index));
  38                /* Flushing the AP interceptor cache to make APR_LMT_MAP_ENTRY_S
  39                 * changes effective. Write 1 for flush and read is being used as a
  40                 * barrier and sets up a data dependency. Write to 0 after a write
  41                 * to 1 to complete the flush.
  42                 */
  43                rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, BIT_ULL(0));
  44                rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_CTL);
  45                rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, 0x00);
  46        }
  47
  48        iounmap(lmt_map_base);
  49        return 0;
  50}
  51
  52#define LMT_MAP_TBL_W1_OFF  8
  53static u32 rvu_get_lmtst_tbl_index(struct rvu *rvu, u16 pcifunc)
  54{
  55        return ((rvu_get_pf(pcifunc) * rvu->hw->total_vfs) +
  56                (pcifunc & RVU_PFVF_FUNC_MASK)) * LMT_MAPTBL_ENTRY_SIZE;
  57}
  58
  59static int rvu_get_lmtaddr(struct rvu *rvu, u16 pcifunc,
  60                           u64 iova, u64 *lmt_addr)
  61{
  62        u64 pa, val, pf;
  63        int err;
  64
  65        if (!iova) {
  66                dev_err(rvu->dev, "%s Requested Null address for transulation\n", __func__);
  67                return -EINVAL;
  68        }
  69
  70        rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_REQ, iova);
  71        pf = rvu_get_pf(pcifunc) & 0x1F;
  72        val = BIT_ULL(63) | BIT_ULL(14) | BIT_ULL(13) | pf << 8 |
  73              ((pcifunc & RVU_PFVF_FUNC_MASK) & 0xFF);
  74        rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TXN_REQ, val);
  75
  76        err = rvu_poll_reg(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_RSP_STS, BIT_ULL(0), false);
  77        if (err) {
  78                dev_err(rvu->dev, "%s LMTLINE iova transulation failed\n", __func__);
  79                return err;
  80        }
  81        val = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_RSP_STS);
  82        if (val & ~0x1ULL) {
  83                dev_err(rvu->dev, "%s LMTLINE iova transulation failed err:%llx\n", __func__, val);
  84                return -EIO;
  85        }
  86        /* PA[51:12] = RVU_AF_SMMU_TLN_FLIT0[57:18]
  87         * PA[11:0] = IOVA[11:0]
  88         */
  89        pa = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TLN_FLIT0) >> 18;
  90        pa &= GENMASK_ULL(39, 0);
  91        *lmt_addr = (pa << 12) | (iova  & 0xFFF);
  92
  93        return 0;
  94}
  95
  96static int rvu_update_lmtaddr(struct rvu *rvu, u16 pcifunc, u64 lmt_addr)
  97{
  98        struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
  99        u32 tbl_idx;
 100        int err = 0;
 101        u64 val;
 102
 103        /* Read the current lmt addr of pcifunc */
 104        tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
 105        err = lmtst_map_table_ops(rvu, tbl_idx, &val, LMT_TBL_OP_READ);
 106        if (err) {
 107                dev_err(rvu->dev,
 108                        "Failed to read LMT map table: index 0x%x err %d\n",
 109                        tbl_idx, err);
 110                return err;
 111        }
 112
 113        /* Storing the seondary's lmt base address as this needs to be
 114         * reverted in FLR. Also making sure this default value doesn't
 115         * get overwritten on multiple calls to this mailbox.
 116         */
 117        if (!pfvf->lmt_base_addr)
 118                pfvf->lmt_base_addr = val;
 119
 120        /* Update the LMT table with new addr */
 121        err = lmtst_map_table_ops(rvu, tbl_idx, &lmt_addr, LMT_TBL_OP_WRITE);
 122        if (err) {
 123                dev_err(rvu->dev,
 124                        "Failed to update LMT map table: index 0x%x err %d\n",
 125                        tbl_idx, err);
 126                return err;
 127        }
 128        return 0;
 129}
 130
 131int rvu_mbox_handler_lmtst_tbl_setup(struct rvu *rvu,
 132                                     struct lmtst_tbl_setup_req *req,
 133                                     struct msg_rsp *rsp)
 134{
 135        struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
 136        u32 pri_tbl_idx, tbl_idx;
 137        u64 lmt_addr;
 138        int err = 0;
 139        u64 val;
 140
 141        /* Check if PF_FUNC wants to use it's own local memory as LMTLINE
 142         * region, if so, convert that IOVA to physical address and
 143         * populate LMT table with that address
 144         */
 145        if (req->use_local_lmt_region) {
 146                err = rvu_get_lmtaddr(rvu, req->hdr.pcifunc,
 147                                      req->lmt_iova, &lmt_addr);
 148                if (err < 0)
 149                        return err;
 150
 151                /* Update the lmt addr for this PFFUNC in the LMT table */
 152                err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, lmt_addr);
 153                if (err)
 154                        return err;
 155        }
 156
 157        /* Reconfiguring lmtst map table in lmt region shared mode i.e. make
 158         * multiple PF_FUNCs to share an LMTLINE region, so primary/base
 159         * pcifunc (which is passed as an argument to mailbox) is the one
 160         * whose lmt base address will be shared among other secondary
 161         * pcifunc (will be the one who is calling this mailbox).
 162         */
 163        if (req->base_pcifunc) {
 164                /* Calculating the LMT table index equivalent to primary
 165                 * pcifunc.
 166                 */
 167                pri_tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->base_pcifunc);
 168
 169                /* Read the base lmt addr of the primary pcifunc */
 170                err = lmtst_map_table_ops(rvu, pri_tbl_idx, &val,
 171                                          LMT_TBL_OP_READ);
 172                if (err) {
 173                        dev_err(rvu->dev,
 174                                "Failed to read LMT map table: index 0x%x err %d\n",
 175                                pri_tbl_idx, err);
 176                        goto error;
 177                }
 178
 179                /* Update the base lmt addr of secondary with primary's base
 180                 * lmt addr.
 181                 */
 182                err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, val);
 183                if (err)
 184                        return err;
 185        }
 186
 187        /* This mailbox can also be used to update word1 of APR_LMT_MAP_ENTRY_S
 188         * like enabling scheduled LMTST, disable LMTLINE prefetch, disable
 189         * early completion for ordered LMTST.
 190         */
 191        if (req->sch_ena || req->dis_sched_early_comp || req->dis_line_pref) {
 192                tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->hdr.pcifunc);
 193                err = lmtst_map_table_ops(rvu, tbl_idx + LMT_MAP_TBL_W1_OFF,
 194                                          &val, LMT_TBL_OP_READ);
 195                if (err) {
 196                        dev_err(rvu->dev,
 197                                "Failed to read LMT map table: index 0x%x err %d\n",
 198                                tbl_idx + LMT_MAP_TBL_W1_OFF, err);
 199                        goto error;
 200                }
 201
 202                /* Storing lmt map table entry word1 default value as this needs
 203                 * to be reverted in FLR. Also making sure this default value
 204                 * doesn't get overwritten on multiple calls to this mailbox.
 205                 */
 206                if (!pfvf->lmt_map_ent_w1)
 207                        pfvf->lmt_map_ent_w1 = val;
 208
 209                /* Disable early completion for Ordered LMTSTs. */
 210                if (req->dis_sched_early_comp)
 211                        val |= (req->dis_sched_early_comp <<
 212                                APR_LMT_MAP_ENT_DIS_SCH_CMP_SHIFT);
 213                /* Enable scheduled LMTST */
 214                if (req->sch_ena)
 215                        val |= (req->sch_ena << APR_LMT_MAP_ENT_SCH_ENA_SHIFT) |
 216                                req->ssow_pf_func;
 217                /* Disables LMTLINE prefetch before receiving store data. */
 218                if (req->dis_line_pref)
 219                        val |= (req->dis_line_pref <<
 220                                APR_LMT_MAP_ENT_DIS_LINE_PREF_SHIFT);
 221
 222                err = lmtst_map_table_ops(rvu, tbl_idx + LMT_MAP_TBL_W1_OFF,
 223                                          &val, LMT_TBL_OP_WRITE);
 224                if (err) {
 225                        dev_err(rvu->dev,
 226                                "Failed to update LMT map table: index 0x%x err %d\n",
 227                                tbl_idx + LMT_MAP_TBL_W1_OFF, err);
 228                        goto error;
 229                }
 230        }
 231
 232error:
 233        return err;
 234}
 235
 236/* Resetting the lmtst map table to original base addresses */
 237void rvu_reset_lmt_map_tbl(struct rvu *rvu, u16 pcifunc)
 238{
 239        struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
 240        u32 tbl_idx;
 241        int err;
 242
 243        if (is_rvu_otx2(rvu))
 244                return;
 245
 246        if (pfvf->lmt_base_addr || pfvf->lmt_map_ent_w1) {
 247                /* This corresponds to lmt map table index */
 248                tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
 249                /* Reverting back original lmt base addr for respective
 250                 * pcifunc.
 251                 */
 252                if (pfvf->lmt_base_addr) {
 253                        err = lmtst_map_table_ops(rvu, tbl_idx,
 254                                                  &pfvf->lmt_base_addr,
 255                                                  LMT_TBL_OP_WRITE);
 256                        if (err)
 257                                dev_err(rvu->dev,
 258                                        "Failed to update LMT map table: index 0x%x err %d\n",
 259                                        tbl_idx, err);
 260                        pfvf->lmt_base_addr = 0;
 261                }
 262                /* Reverting back to orginal word1 val of lmtst map table entry
 263                 * which underwent changes.
 264                 */
 265                if (pfvf->lmt_map_ent_w1) {
 266                        err = lmtst_map_table_ops(rvu,
 267                                                  tbl_idx + LMT_MAP_TBL_W1_OFF,
 268                                                  &pfvf->lmt_map_ent_w1,
 269                                                  LMT_TBL_OP_WRITE);
 270                        if (err)
 271                                dev_err(rvu->dev,
 272                                        "Failed to update LMT map table: index 0x%x err %d\n",
 273                                        tbl_idx + LMT_MAP_TBL_W1_OFF, err);
 274                        pfvf->lmt_map_ent_w1 = 0;
 275                }
 276        }
 277}
 278
 279int rvu_set_channels_base(struct rvu *rvu)
 280{
 281        u16 nr_lbk_chans, nr_sdp_chans, nr_cgx_chans, nr_cpt_chans;
 282        u16 sdp_chan_base, cgx_chan_base, cpt_chan_base;
 283        struct rvu_hwinfo *hw = rvu->hw;
 284        u64 nix_const, nix_const1;
 285        int blkaddr;
 286
 287        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 288        if (blkaddr < 0)
 289                return blkaddr;
 290
 291        nix_const = rvu_read64(rvu, blkaddr, NIX_AF_CONST);
 292        nix_const1 = rvu_read64(rvu, blkaddr, NIX_AF_CONST1);
 293
 294        hw->cgx = (nix_const >> 12) & 0xFULL;
 295        hw->lmac_per_cgx = (nix_const >> 8) & 0xFULL;
 296        hw->cgx_links = hw->cgx * hw->lmac_per_cgx;
 297        hw->lbk_links = (nix_const >> 24) & 0xFULL;
 298        hw->cpt_links = (nix_const >> 44) & 0xFULL;
 299        hw->sdp_links = 1;
 300
 301        hw->cgx_chan_base = NIX_CHAN_CGX_LMAC_CHX(0, 0, 0);
 302        hw->lbk_chan_base = NIX_CHAN_LBK_CHX(0, 0);
 303        hw->sdp_chan_base = NIX_CHAN_SDP_CH_START;
 304
 305        /* No Programmable channels */
 306        if (!(nix_const & BIT_ULL(60)))
 307                return 0;
 308
 309        hw->cap.programmable_chans = true;
 310
 311        /* If programmable channels are present then configure
 312         * channels such that all channel numbers are contiguous
 313         * leaving no holes. This way the new CPT channels can be
 314         * accomodated. The order of channel numbers assigned is
 315         * LBK, SDP, CGX and CPT. Also the base channel number
 316         * of a block must be multiple of number of channels
 317         * of the block.
 318         */
 319        nr_lbk_chans = (nix_const >> 16) & 0xFFULL;
 320        nr_sdp_chans = nix_const1 & 0xFFFULL;
 321        nr_cgx_chans = nix_const & 0xFFULL;
 322        nr_cpt_chans = (nix_const >> 32) & 0xFFFULL;
 323
 324        sdp_chan_base = hw->lbk_chan_base + hw->lbk_links * nr_lbk_chans;
 325        /* Round up base channel to multiple of number of channels */
 326        hw->sdp_chan_base = ALIGN(sdp_chan_base, nr_sdp_chans);
 327
 328        cgx_chan_base = hw->sdp_chan_base + hw->sdp_links * nr_sdp_chans;
 329        hw->cgx_chan_base = ALIGN(cgx_chan_base, nr_cgx_chans);
 330
 331        cpt_chan_base = hw->cgx_chan_base + hw->cgx_links * nr_cgx_chans;
 332        hw->cpt_chan_base = ALIGN(cpt_chan_base, nr_cpt_chans);
 333
 334        /* Out of 4096 channels start CPT from 2048 so
 335         * that MSB for CPT channels is always set
 336         */
 337        if (cpt_chan_base <= 0x800) {
 338                hw->cpt_chan_base = 0x800;
 339        } else {
 340                dev_err(rvu->dev,
 341                        "CPT channels could not fit in the range 2048-4095\n");
 342                return -EINVAL;
 343        }
 344
 345        return 0;
 346}
 347
 348#define LBK_CONNECT_NIXX(a)             (0x0 + (a))
 349
 350static void __rvu_lbk_set_chans(struct rvu *rvu, void __iomem *base,
 351                                u64 offset, int lbkid, u16 chans)
 352{
 353        struct rvu_hwinfo *hw = rvu->hw;
 354        u64 cfg;
 355
 356        cfg = readq(base + offset);
 357        cfg &= ~(LBK_LINK_CFG_RANGE_MASK |
 358                 LBK_LINK_CFG_ID_MASK | LBK_LINK_CFG_BASE_MASK);
 359        cfg |=  FIELD_PREP(LBK_LINK_CFG_RANGE_MASK, ilog2(chans));
 360        cfg |=  FIELD_PREP(LBK_LINK_CFG_ID_MASK, lbkid);
 361        cfg |=  FIELD_PREP(LBK_LINK_CFG_BASE_MASK, hw->lbk_chan_base);
 362
 363        writeq(cfg, base + offset);
 364}
 365
 366static void rvu_lbk_set_channels(struct rvu *rvu)
 367{
 368        struct pci_dev *pdev = NULL;
 369        void __iomem *base;
 370        u64 lbk_const;
 371        u8 src, dst;
 372        u16 chans;
 373
 374        /* To loopback packets between multiple NIX blocks
 375         * mutliple LBK blocks are needed. With two NIX blocks,
 376         * four LBK blocks are needed and each LBK block
 377         * source and destination are as follows:
 378         * LBK0 - source NIX0 and destination NIX1
 379         * LBK1 - source NIX0 and destination NIX1
 380         * LBK2 - source NIX1 and destination NIX0
 381         * LBK3 - source NIX1 and destination NIX1
 382         * As per the HRM channel numbers should be programmed as:
 383         * P2X and X2P of LBK0 as same
 384         * P2X and X2P of LBK3 as same
 385         * P2X of LBK1 and X2P of LBK2 as same
 386         * P2X of LBK2 and X2P of LBK1 as same
 387         */
 388        while (true) {
 389                pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
 390                                      PCI_DEVID_OCTEONTX2_LBK, pdev);
 391                if (!pdev)
 392                        return;
 393
 394                base = pci_ioremap_bar(pdev, 0);
 395                if (!base)
 396                        goto err_put;
 397
 398                lbk_const = readq(base + LBK_CONST);
 399                chans = FIELD_GET(LBK_CONST_CHANS, lbk_const);
 400                dst = FIELD_GET(LBK_CONST_DST, lbk_const);
 401                src = FIELD_GET(LBK_CONST_SRC, lbk_const);
 402
 403                if (src == dst) {
 404                        if (src == LBK_CONNECT_NIXX(0)) { /* LBK0 */
 405                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
 406                                                    0, chans);
 407                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
 408                                                    0, chans);
 409                        } else if (src == LBK_CONNECT_NIXX(1)) { /* LBK3 */
 410                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
 411                                                    1, chans);
 412                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
 413                                                    1, chans);
 414                        }
 415                } else {
 416                        if (src == LBK_CONNECT_NIXX(0)) { /* LBK1 */
 417                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
 418                                                    0, chans);
 419                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
 420                                                    1, chans);
 421                        } else if (src == LBK_CONNECT_NIXX(1)) { /* LBK2 */
 422                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
 423                                                    1, chans);
 424                                __rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
 425                                                    0, chans);
 426                        }
 427                }
 428                iounmap(base);
 429        }
 430err_put:
 431        pci_dev_put(pdev);
 432}
 433
 434static void __rvu_nix_set_channels(struct rvu *rvu, int blkaddr)
 435{
 436        u64 nix_const1 = rvu_read64(rvu, blkaddr, NIX_AF_CONST1);
 437        u64 nix_const = rvu_read64(rvu, blkaddr, NIX_AF_CONST);
 438        u16 cgx_chans, lbk_chans, sdp_chans, cpt_chans;
 439        struct rvu_hwinfo *hw = rvu->hw;
 440        int link, nix_link = 0;
 441        u16 start;
 442        u64 cfg;
 443
 444        cgx_chans = nix_const & 0xFFULL;
 445        lbk_chans = (nix_const >> 16) & 0xFFULL;
 446        sdp_chans = nix_const1 & 0xFFFULL;
 447        cpt_chans = (nix_const >> 32) & 0xFFFULL;
 448
 449        start = hw->cgx_chan_base;
 450        for (link = 0; link < hw->cgx_links; link++, nix_link++) {
 451                cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
 452                cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
 453                cfg |=  FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(cgx_chans));
 454                cfg |=  FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
 455                rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
 456                start += cgx_chans;
 457        }
 458
 459        start = hw->lbk_chan_base;
 460        for (link = 0; link < hw->lbk_links; link++, nix_link++) {
 461                cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
 462                cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
 463                cfg |=  FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(lbk_chans));
 464                cfg |=  FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
 465                rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
 466                start += lbk_chans;
 467        }
 468
 469        start = hw->sdp_chan_base;
 470        for (link = 0; link < hw->sdp_links; link++, nix_link++) {
 471                cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
 472                cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
 473                cfg |=  FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(sdp_chans));
 474                cfg |=  FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
 475                rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
 476                start += sdp_chans;
 477        }
 478
 479        start = hw->cpt_chan_base;
 480        for (link = 0; link < hw->cpt_links; link++, nix_link++) {
 481                cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
 482                cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
 483                cfg |=  FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(cpt_chans));
 484                cfg |=  FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
 485                rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
 486                start += cpt_chans;
 487        }
 488}
 489
 490static void rvu_nix_set_channels(struct rvu *rvu)
 491{
 492        int blkaddr = 0;
 493
 494        blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
 495        while (blkaddr) {
 496                __rvu_nix_set_channels(rvu, blkaddr);
 497                blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
 498        }
 499}
 500
 501static void __rvu_rpm_set_channels(int cgxid, int lmacid, u16 base)
 502{
 503        u64 cfg;
 504
 505        cfg = cgx_lmac_read(cgxid, lmacid, RPMX_CMRX_LINK_CFG);
 506        cfg &= ~(RPMX_CMRX_LINK_BASE_MASK | RPMX_CMRX_LINK_RANGE_MASK);
 507
 508        /* There is no read-only constant register to read
 509         * the number of channels for LMAC and it is always 16.
 510         */
 511        cfg |=  FIELD_PREP(RPMX_CMRX_LINK_RANGE_MASK, ilog2(16));
 512        cfg |=  FIELD_PREP(RPMX_CMRX_LINK_BASE_MASK, base);
 513        cgx_lmac_write(cgxid, lmacid, RPMX_CMRX_LINK_CFG, cfg);
 514}
 515
 516static void rvu_rpm_set_channels(struct rvu *rvu)
 517{
 518        struct rvu_hwinfo *hw = rvu->hw;
 519        u16 base = hw->cgx_chan_base;
 520        int cgx, lmac;
 521
 522        for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) {
 523                for (lmac = 0; lmac < hw->lmac_per_cgx; lmac++) {
 524                        __rvu_rpm_set_channels(cgx, lmac, base);
 525                        base += 16;
 526                }
 527        }
 528}
 529
 530void rvu_program_channels(struct rvu *rvu)
 531{
 532        struct rvu_hwinfo *hw = rvu->hw;
 533
 534        if (!hw->cap.programmable_chans)
 535                return;
 536
 537        rvu_nix_set_channels(rvu);
 538        rvu_lbk_set_channels(rvu);
 539        rvu_rpm_set_channels(rvu);
 540}
 541