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