uboot/arch/powerpc/cpu/mpc85xx/liodn.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2008-2011 Freescale Semiconductor, Inc.
   4 */
   5
   6#include <common.h>
   7#include <linux/libfdt.h>
   8#include <fdt_support.h>
   9
  10#include <asm/immap_85xx.h>
  11#include <asm/io.h>
  12#include <asm/processor.h>
  13#include <asm/fsl_portals.h>
  14#include <asm/fsl_liodn.h>
  15
  16int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset)
  17{
  18        liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset;
  19
  20        if (liodn_bases[dpaa_dev].num_ids == 2)
  21                liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset;
  22
  23        return liodn_bases[dpaa_dev].num_ids;
  24}
  25
  26#ifdef CONFIG_SYS_SRIO
  27static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size)
  28{
  29        int i;
  30
  31        for (i = 0; i < size; i++) {
  32                unsigned long reg_off = tbl[i].reg_offset[0];
  33                out_be32((u32 *)reg_off, tbl[i].id[0]);
  34
  35                if (tbl[i].num_ids == 2) {
  36                        reg_off = tbl[i].reg_offset[1];
  37                        out_be32((u32 *)reg_off, tbl[i].id[1]);
  38                }
  39        }
  40}
  41#endif
  42
  43static void set_liodn(struct liodn_id_table *tbl, int size)
  44{
  45        int i;
  46
  47        for (i = 0; i < size; i++) {
  48                u32 liodn;
  49                if (tbl[i].num_ids == 2) {
  50                        liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
  51                } else {
  52                        liodn = tbl[i].id[0];
  53                }
  54
  55                out_be32((volatile u32 *)(tbl[i].reg_offset), liodn);
  56        }
  57}
  58
  59#ifdef CONFIG_SYS_DPAA_FMAN
  60static void set_fman_liodn(struct fman_liodn_id_table *tbl, int size)
  61{
  62        int i;
  63
  64        for (i = 0; i < size; i++) {
  65                u32 liodn;
  66                if (tbl[i].num_ids == 2)
  67                        liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
  68                else
  69                        liodn = tbl[i].id[0];
  70
  71                out_be32((volatile u32 *)(tbl[i].reg_offset), liodn);
  72        }
  73}
  74#endif
  75
  76static void setup_sec_liodn_base(void)
  77{
  78        ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  79        u32 base;
  80
  81        if (!IS_E_PROCESSOR(get_svr()))
  82                return;
  83
  84        /* QILCR[QSLOM] */
  85        sec_out32(&sec->qilcr_ms, 0x3ff<<16);
  86
  87        base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) |
  88                liodn_bases[FSL_HW_PORTAL_SEC].id[1];
  89
  90        sec_out32(&sec->qilcr_ls, base);
  91}
  92
  93#ifdef CONFIG_SYS_DPAA_FMAN
  94static void setup_fman_liodn_base(enum fsl_dpaa_dev dev,
  95                                  struct fman_liodn_id_table *tbl, int size)
  96{
  97        int i;
  98        ccsr_fman_t *fm;
  99        u32 base;
 100
 101        switch(dev) {
 102        case FSL_HW_PORTAL_FMAN1:
 103                fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
 104                break;
 105
 106#if (CONFIG_SYS_NUM_FMAN == 2)
 107        case FSL_HW_PORTAL_FMAN2:
 108                fm = (void *)CONFIG_SYS_FSL_FM2_ADDR;
 109                break;
 110#endif
 111        default:
 112                printf("Error: Invalid device type to %s\n", __FUNCTION__);
 113                return ;
 114        }
 115
 116        base = (liodn_bases[dev].id[0] << 16) | liodn_bases[dev].id[0];
 117
 118        /* setup all bases the same */
 119        for (i = 0; i < 32; i++) {
 120                out_be32(&fm->fm_dma.fmdmplr[i], base);
 121        }
 122
 123        /* update tbl to ... */
 124        for (i = 0; i < size; i++)
 125                tbl[i].id[0] += liodn_bases[dev].id[0];
 126}
 127#endif
 128
 129static void setup_pme_liodn_base(void)
 130{
 131#ifdef CONFIG_SYS_DPAA_PME
 132        ccsr_pme_t *pme = (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
 133        u32 base = (liodn_bases[FSL_HW_PORTAL_PME].id[0] << 16) |
 134                        liodn_bases[FSL_HW_PORTAL_PME].id[1];
 135
 136        out_be32(&pme->liodnbr, base);
 137#endif
 138}
 139
 140#ifdef CONFIG_SYS_FSL_RAID_ENGINE
 141static void setup_raide_liodn_base(void)
 142{
 143        struct ccsr_raide *raide = (void *)CONFIG_SYS_FSL_RAID_ENGINE_ADDR;
 144
 145        /* setup raid engine liodn base for data/desc ; both set to 47 */
 146        u32 base = (liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0] << 16) |
 147                        liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0];
 148
 149        out_be32(&raide->liodnbr, base);
 150}
 151#endif
 152
 153#ifdef CONFIG_SYS_DPAA_RMAN
 154static void set_rman_liodn(struct liodn_id_table *tbl, int size)
 155{
 156        int i;
 157        struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
 158
 159        for (i = 0; i < size; i++) {
 160                /* write the RMan block number */
 161                out_be32(&rman->mmitar, i);
 162                /* write the liodn offset corresponding to the block */
 163                out_be32((u32 *)(tbl[i].reg_offset), tbl[i].id[0]);
 164        }
 165}
 166
 167static void setup_rman_liodn_base(struct liodn_id_table *tbl, int size)
 168{
 169        int i;
 170        struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
 171        u32 base = liodn_bases[FSL_HW_PORTAL_RMAN].id[0];
 172
 173        out_be32(&rman->mmliodnbr, base);
 174
 175        /* update liodn offset */
 176        for (i = 0; i < size; i++)
 177                tbl[i].id[0] += base;
 178}
 179#endif
 180
 181void set_liodns(void)
 182{
 183        /* setup general liodn offsets */
 184        set_liodn(liodn_tbl, liodn_tbl_sz);
 185
 186#ifdef CONFIG_SYS_SRIO
 187        /* setup SRIO port liodns */
 188        set_srio_liodn(srio_liodn_tbl, srio_liodn_tbl_sz);
 189#endif
 190
 191        /* setup SEC block liodn bases & offsets if we have one */
 192        if (IS_E_PROCESSOR(get_svr())) {
 193                set_liodn(sec_liodn_tbl, sec_liodn_tbl_sz);
 194                setup_sec_liodn_base();
 195        }
 196
 197        /* setup FMAN block(s) liodn bases & offsets if we have one */
 198#ifdef CONFIG_SYS_DPAA_FMAN
 199        set_fman_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz);
 200        setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl,
 201                                fman1_liodn_tbl_sz);
 202
 203#if (CONFIG_SYS_NUM_FMAN == 2)
 204        set_fman_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz);
 205        setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl,
 206                                fman2_liodn_tbl_sz);
 207#endif
 208#endif
 209        /* setup PME liodn base */
 210        setup_pme_liodn_base();
 211
 212#ifdef CONFIG_SYS_FSL_RAID_ENGINE
 213        /* raid engine ccr addr code for liodn */
 214        set_liodn(raide_liodn_tbl, raide_liodn_tbl_sz);
 215        setup_raide_liodn_base();
 216#endif
 217
 218#ifdef CONFIG_SYS_DPAA_RMAN
 219        /* setup RMan liodn offsets */
 220        set_rman_liodn(rman_liodn_tbl, rman_liodn_tbl_sz);
 221        /* setup RMan liodn base */
 222        setup_rman_liodn_base(rman_liodn_tbl, rman_liodn_tbl_sz);
 223#endif
 224}
 225
 226#ifdef CONFIG_SYS_SRIO
 227static void fdt_fixup_srio_liodn(void *blob, struct srio_liodn_id_table *tbl)
 228{
 229        int i, srio_off;
 230
 231        /* search for srio node, if doesn't exist just return - nothing todo */
 232        srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio");
 233        if (srio_off < 0)
 234                return ;
 235
 236        for (i = 0; i < srio_liodn_tbl_sz; i++) {
 237                int off, portid = tbl[i].portid;
 238
 239                off = fdt_node_offset_by_prop_value(blob, srio_off,
 240                         "cell-index", &portid, 4);
 241                if (off >= 0) {
 242                        off = fdt_setprop(blob, off, "fsl,liodn",
 243                                &tbl[i].id[0],
 244                                sizeof(u32) * tbl[i].num_ids);
 245                        if (off > 0)
 246                                printf("WARNING unable to set fsl,liodn for "
 247                                        "fsl,srio port %d: %s\n",
 248                                        portid, fdt_strerror(off));
 249                } else {
 250                        debug("WARNING: couldn't set fsl,liodn for srio: %s.\n",
 251                                fdt_strerror(off));
 252                }
 253        }
 254}
 255#endif
 256
 257#define CONFIG_SYS_MAX_PCI_EPS          8
 258
 259static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat,
 260                                        int ep_liodn_start)
 261{
 262        int off, pci_idx = 0, pci_cnt = 0, i, rc;
 263        const uint32_t *base_liodn;
 264        uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 };
 265
 266        /*
 267         * Count the number of pci nodes.
 268         * It's needed later when the interleaved liodn offsets are generated.
 269         */
 270        off = fdt_node_offset_by_compatible(fdt, -1, compat);
 271        while (off != -FDT_ERR_NOTFOUND) {
 272                pci_cnt++;
 273                off = fdt_node_offset_by_compatible(fdt, off, compat);
 274        }
 275
 276        for (off = fdt_node_offset_by_compatible(fdt, -1, compat);
 277             off != -FDT_ERR_NOTFOUND;
 278             off = fdt_node_offset_by_compatible(fdt, off, compat)) {
 279                base_liodn = fdt_getprop(fdt, off, "fsl,liodn", &rc);
 280                if (!base_liodn) {
 281                        char path[64];
 282
 283                        if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
 284                                strcpy(path, "(unknown)");
 285                        printf("WARNING Could not get liodn of node %s: %s\n",
 286                               path, fdt_strerror(rc));
 287                        continue;
 288                }
 289                for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++)
 290                        liodn_offs[i + 1] = ep_liodn_start +
 291                                        i * pci_cnt + pci_idx - *base_liodn;
 292                rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list",
 293                                 liodn_offs, sizeof(liodn_offs));
 294                if (rc) {
 295                        char path[64];
 296
 297                        if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
 298                                strcpy(path, "(unknown)");
 299                        printf("WARNING Unable to set fsl,liodn-offset-list for "
 300                               "node %s: %s\n", path, fdt_strerror(rc));
 301                        continue;
 302                }
 303                pci_idx++;
 304        }
 305}
 306
 307static void fdt_fixup_liodn_tbl(void *blob, struct liodn_id_table *tbl, int sz)
 308{
 309        int i;
 310
 311        for (i = 0; i < sz; i++) {
 312                int off;
 313
 314                if (tbl[i].compat == NULL)
 315                        continue;
 316
 317                off = fdt_node_offset_by_compat_reg(blob,
 318                                tbl[i].compat, tbl[i].compat_offset);
 319                if (off >= 0) {
 320                        off = fdt_setprop(blob, off, "fsl,liodn",
 321                                &tbl[i].id[0],
 322                                sizeof(u32) * tbl[i].num_ids);
 323                        if (off > 0)
 324                                printf("WARNING unable to set fsl,liodn for "
 325                                        "%s: %s\n",
 326                                        tbl[i].compat, fdt_strerror(off));
 327                } else {
 328                        debug("WARNING: could not set fsl,liodn for %s: %s.\n",
 329                                        tbl[i].compat, fdt_strerror(off));
 330                }
 331        }
 332}
 333
 334#ifdef CONFIG_SYS_DPAA_FMAN
 335static void fdt_fixup_liodn_tbl_fman(void *blob,
 336                                     struct fman_liodn_id_table *tbl,
 337                                     int sz)
 338{
 339        int i;
 340
 341        for (i = 0; i < sz; i++) {
 342                int off;
 343
 344                if (tbl[i].compat == NULL)
 345                        continue;
 346
 347                /* Try the new compatible first.
 348                 * If the node is missing, try the old.
 349                 */
 350                off = fdt_node_offset_by_compat_reg(blob,
 351                                tbl[i].compat[0], tbl[i].compat_offset);
 352                if (off < 0)
 353                        off = fdt_node_offset_by_compat_reg(blob,
 354                                        tbl[i].compat[1], tbl[i].compat_offset);
 355
 356                if (off >= 0) {
 357                        off = fdt_setprop(blob, off, "fsl,liodn",
 358                                &tbl[i].id[0],
 359                                sizeof(u32) * tbl[i].num_ids);
 360                        if (off > 0)
 361                                printf("WARNING unable to set fsl,liodn for FMan Port: %s\n",
 362                                       fdt_strerror(off));
 363                } else {
 364                        debug("WARNING: could not set fsl,liodn for FMan Portport: %s.\n",
 365                              fdt_strerror(off));
 366                }
 367        }
 368}
 369#endif
 370
 371void fdt_fixup_liodn(void *blob)
 372{
 373#ifdef CONFIG_SYS_SRIO
 374        fdt_fixup_srio_liodn(blob, srio_liodn_tbl);
 375#endif
 376
 377        fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz);
 378#ifdef CONFIG_SYS_DPAA_FMAN
 379        fdt_fixup_liodn_tbl_fman(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz);
 380#if (CONFIG_SYS_NUM_FMAN == 2)
 381        fdt_fixup_liodn_tbl_fman(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz);
 382#endif
 383#endif
 384        fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz);
 385
 386#ifdef CONFIG_SYS_FSL_RAID_ENGINE
 387        fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz);
 388#endif
 389
 390#ifdef CONFIG_SYS_DPAA_RMAN
 391        fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz);
 392#endif
 393
 394        ccsr_pcix_t *pcix = (ccsr_pcix_t *)CONFIG_SYS_PCIE1_ADDR;
 395        int pci_ver = pcix->ipver1 & 0xffff, liodn_base = 0;
 396
 397        if (pci_ver >= 0x0204) {
 398                if (pci_ver >= 0x0300)
 399                        liodn_base = 1024;
 400                else
 401                        liodn_base = 256;
 402        }
 403
 404        if (liodn_base) {
 405                char compat[32];
 406
 407                sprintf(compat, "fsl,qoriq-pcie-v%d.%d",
 408                        (pci_ver & 0xff00) >> 8, pci_ver & 0xff);
 409                fdt_fixup_pci_liodn_offsets(blob, compat, liodn_base);
 410                fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie", liodn_base);
 411        }
 412}
 413