uboot/drivers/misc/fsl_portals.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2008-2011 Freescale Semiconductor, Inc.
   4 * Copyright 2017 NXP
   5 */
   6
   7#include <common.h>
   8#include <log.h>
   9#include <linux/libfdt.h>
  10#include <fdt_support.h>
  11
  12#include <asm/processor.h>
  13#include <asm/io.h>
  14#ifdef CONFIG_PPC
  15#include <asm/fsl_portals.h>
  16#include <asm/fsl_liodn.h>
  17#else
  18#include <asm/arch-fsl-layerscape/fsl_portals.h>
  19#include <asm/arch-fsl-layerscape/fsl_icid.h>
  20#endif
  21#include <fsl_qbman.h>
  22
  23#define MAX_BPORTALS (CONFIG_SYS_BMAN_CINH_SIZE / CONFIG_SYS_BMAN_SP_CINH_SIZE)
  24#define MAX_QPORTALS (CONFIG_SYS_QMAN_CINH_SIZE / CONFIG_SYS_QMAN_SP_CINH_SIZE)
  25void setup_qbman_portals(void)
  26{
  27        void __iomem *bpaddr = (void *)CONFIG_SYS_BMAN_CINH_BASE +
  28                                CONFIG_SYS_BMAN_SWP_ISDR_REG;
  29        void __iomem *qpaddr = (void *)CONFIG_SYS_QMAN_CINH_BASE +
  30                                CONFIG_SYS_QMAN_SWP_ISDR_REG;
  31        struct ccsr_qman *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
  32
  33        /* Set the Qman initiator BAR to match the LAW (for DQRR stashing) */
  34#ifdef CONFIG_PHYS_64BIT
  35        out_be32(&qman->qcsp_bare, (u32)(CONFIG_SYS_QMAN_MEM_PHYS >> 32));
  36#endif
  37        out_be32(&qman->qcsp_bar, (u32)CONFIG_SYS_QMAN_MEM_PHYS);
  38#ifdef CONFIG_FSL_CORENET
  39        int i;
  40
  41        for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) {
  42                u8 sdest = qp_info[i].sdest;
  43                u16 fliodn = qp_info[i].fliodn;
  44                u16 dliodn = qp_info[i].dliodn;
  45                u16 liodn_off = qp_info[i].liodn_offset;
  46
  47                out_be32(&qman->qcsp[i].qcsp_lio_cfg, (liodn_off << 16) |
  48                                        dliodn);
  49                /* set frame liodn */
  50                out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | fliodn);
  51        }
  52#else
  53#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
  54        int i;
  55
  56        for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) {
  57                u8 sdest = qp_info[i].sdest;
  58                u16 ficid = qp_info[i].ficid;
  59                u16 dicid = qp_info[i].dicid;
  60                u16 icid = qp_info[i].icid;
  61
  62                out_be32(&qman->qcsp[i].qcsp_lio_cfg, (icid << 16) |
  63                                        dicid);
  64                /* set frame icid */
  65                out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | ficid);
  66        }
  67#endif
  68#endif
  69
  70        /* Change default state of BMan ISDR portals to all 1s */
  71        inhibit_portals(bpaddr, CONFIG_SYS_BMAN_NUM_PORTALS, MAX_BPORTALS,
  72                        CONFIG_SYS_BMAN_SP_CINH_SIZE);
  73        inhibit_portals(qpaddr, CONFIG_SYS_QMAN_NUM_PORTALS, MAX_QPORTALS,
  74                        CONFIG_SYS_QMAN_SP_CINH_SIZE);
  75}
  76
  77void inhibit_portals(void __iomem *addr, int max_portals,
  78                     int arch_max_portals, int portal_cinh_size)
  79{
  80        u32 val;
  81        int i;
  82
  83        /* arch_max_portals is the maximum based on memory size. This includes
  84         * the reserved memory in the SoC.  max_portals the number of physical
  85         * portals in the SoC
  86         */
  87        if (max_portals > arch_max_portals) {
  88                printf("ERROR: portal config error\n");
  89                max_portals = arch_max_portals;
  90        }
  91
  92        for (i = 0; i < max_portals; i++) {
  93                out_be32(addr, -1);
  94                val = in_be32(addr);
  95                if (!val) {
  96                        printf("ERROR: Stopped after %d portals\n", i);
  97                        return;
  98                }
  99                addr += portal_cinh_size;
 100        }
 101        debug("Cleared %d portals\n", i);
 102}
 103
 104#ifdef CONFIG_PPC
 105static int fdt_qportal(void *blob, int off, int id, char *name,
 106                       enum fsl_dpaa_dev dev, int create)
 107{
 108        int childoff, dev_off, ret = 0;
 109        u32 dev_handle;
 110#ifdef CONFIG_FSL_CORENET
 111        int num;
 112        u32 liodns[2];
 113#endif
 114
 115        childoff = fdt_subnode_offset(blob, off, name);
 116        if (create) {
 117                char handle[64], *p;
 118
 119                strncpy(handle, name, sizeof(handle));
 120                p = strchr(handle, '@');
 121                if (!strncmp(name, "fman", 4)) {
 122                        *p = *(p + 1);
 123                        p++;
 124                }
 125                *p = '\0';
 126
 127                dev_off = fdt_path_offset(blob, handle);
 128                /* skip this node if alias is not found */
 129                if (dev_off == -FDT_ERR_BADPATH)
 130                        return 0;
 131                if (dev_off < 0)
 132                        return dev_off;
 133
 134                if (childoff <= 0)
 135                        childoff = fdt_add_subnode(blob, off, name);
 136
 137                /* need to update the dev_off after adding a subnode */
 138                dev_off = fdt_path_offset(blob, handle);
 139                if (dev_off < 0)
 140                        return dev_off;
 141
 142                if (childoff > 0) {
 143                        dev_handle = fdt_get_phandle(blob, dev_off);
 144                        if (dev_handle <= 0) {
 145                                dev_handle = fdt_alloc_phandle(blob);
 146                                ret = fdt_set_phandle(blob, dev_off,
 147                                                      dev_handle);
 148                                if (ret < 0)
 149                                        return ret;
 150                        }
 151
 152                        ret = fdt_setprop(blob, childoff, "dev-handle",
 153                                          &dev_handle, sizeof(dev_handle));
 154                        if (ret < 0)
 155                                return ret;
 156
 157#ifdef CONFIG_FSL_CORENET
 158                        num = get_dpaa_liodn(dev, &liodns[0], id);
 159                        ret = fdt_setprop(blob, childoff, "fsl,liodn",
 160                                          &liodns[0], sizeof(u32) * num);
 161                        if (!strncmp(name, "pme", 3)) {
 162                                u32 pme_rev1, pme_rev2;
 163                                ccsr_pme_t *pme_regs =
 164                                        (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
 165
 166                                pme_rev1 = in_be32(&pme_regs->pm_ip_rev_1);
 167                                pme_rev2 = in_be32(&pme_regs->pm_ip_rev_2);
 168                                ret = fdt_setprop(blob, childoff,
 169                                                  "fsl,pme-rev1", &pme_rev1,
 170                                                  sizeof(u32));
 171                                if (ret < 0)
 172                                        return ret;
 173                                ret = fdt_setprop(blob, childoff,
 174                                                  "fsl,pme-rev2", &pme_rev2,
 175                                                  sizeof(u32));
 176                        }
 177#endif
 178                } else {
 179                        return childoff;
 180                }
 181        } else {
 182                if (childoff > 0)
 183                        ret = fdt_del_node(blob, childoff);
 184        }
 185
 186        return ret;
 187}
 188#endif /* CONFIG_PPC */
 189
 190void fdt_fixup_qportals(void *blob)
 191{
 192        int off, err;
 193        unsigned int maj, min;
 194        unsigned int ip_cfg;
 195        struct ccsr_qman *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
 196        u32 rev_1 = in_be32(&qman->ip_rev_1);
 197        u32 rev_2 = in_be32(&qman->ip_rev_2);
 198        char compat[64];
 199        int compat_len;
 200
 201#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
 202        int smmu_ph = fdt_get_smmu_phandle(blob);
 203#endif
 204
 205        maj = (rev_1 >> 8) & 0xff;
 206        min = rev_1 & 0xff;
 207        ip_cfg = rev_2 & 0xff;
 208
 209        compat_len = sprintf(compat, "fsl,qman-portal-%u.%u.%u",
 210                             maj, min, ip_cfg) + 1;
 211        compat_len += sprintf(compat + compat_len, "fsl,qman-portal") + 1;
 212
 213        off = fdt_node_offset_by_compatible(blob, -1, "fsl,qman-portal");
 214        while (off != -FDT_ERR_NOTFOUND) {
 215#if defined(CONFIG_PPC) || defined(CONFIG_ARCH_LS1043A) || \
 216defined(CONFIG_ARCH_LS1046A)
 217#ifdef CONFIG_FSL_CORENET
 218                u32 liodns[2];
 219#endif
 220                const int *ci = fdt_getprop(blob, off, "cell-index", &err);
 221                int i;
 222
 223                if (!ci)
 224                        goto err;
 225
 226                i = fdt32_to_cpu(*ci);
 227#if defined(CONFIG_SYS_DPAA_FMAN) && defined(CONFIG_PPC)
 228                int j;
 229#endif
 230
 231#endif /* CONFIG_PPC || CONFIG_ARCH_LS1043A || CONFIG_ARCH_LS1046A */
 232                err = fdt_setprop(blob, off, "compatible", compat, compat_len);
 233                if (err < 0)
 234                        goto err;
 235#ifdef CONFIG_PPC
 236#ifdef CONFIG_FSL_CORENET
 237                liodns[0] = qp_info[i].dliodn;
 238                liodns[1] = qp_info[i].fliodn;
 239                err = fdt_setprop(blob, off, "fsl,liodn",
 240                                  &liodns, sizeof(u32) * 2);
 241                if (err < 0)
 242                        goto err;
 243#endif
 244
 245                i++;
 246
 247                err = fdt_qportal(blob, off, i, "crypto@0", FSL_HW_PORTAL_SEC,
 248                                  IS_E_PROCESSOR(get_svr()));
 249                if (err < 0)
 250                        goto err;
 251
 252#ifdef CONFIG_FSL_CORENET
 253#ifdef CONFIG_SYS_DPAA_PME
 254                err = fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 1);
 255                if (err < 0)
 256                        goto err;
 257#else
 258                fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 0);
 259#endif
 260#endif
 261
 262#ifdef CONFIG_SYS_DPAA_FMAN
 263                for (j = 0; j < CONFIG_SYS_NUM_FMAN; j++) {
 264                        char name[] = "fman@0";
 265
 266                        name[sizeof(name) - 2] = '0' + j;
 267                        err = fdt_qportal(blob, off, i, name,
 268                                          FSL_HW_PORTAL_FMAN1 + j, 1);
 269                        if (err < 0)
 270                                goto err;
 271                }
 272#endif
 273#ifdef CONFIG_SYS_DPAA_RMAN
 274                err = fdt_qportal(blob, off, i, "rman@0",
 275                                  FSL_HW_PORTAL_RMAN, 1);
 276                if (err < 0)
 277                        goto err;
 278#endif
 279#else
 280#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
 281                if (smmu_ph >= 0) {
 282                        u32 icids[3];
 283
 284                        icids[0] = qp_info[i].icid;
 285                        icids[1] = qp_info[i].dicid;
 286                        icids[2] = qp_info[i].ficid;
 287
 288                        fdt_set_iommu_prop(blob, off, smmu_ph, icids, 3);
 289                }
 290#endif
 291#endif /* CONFIG_PPC */
 292
 293err:
 294                if (err < 0) {
 295                        printf("ERROR: unable to create props for %s: %s\n",
 296                               fdt_get_name(blob, off, NULL),
 297                               fdt_strerror(err));
 298                        return;
 299                }
 300
 301                off = fdt_node_offset_by_compatible(blob, off,
 302                                                    "fsl,qman-portal");
 303        }
 304}
 305
 306void fdt_fixup_bportals(void *blob)
 307{
 308        int off, err;
 309        unsigned int maj, min;
 310        unsigned int ip_cfg;
 311        struct ccsr_bman *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR;
 312        u32 rev_1 = in_be32(&bman->ip_rev_1);
 313        u32 rev_2 = in_be32(&bman->ip_rev_2);
 314        char compat[64];
 315        int compat_len;
 316
 317        maj = (rev_1 >> 8) & 0xff;
 318        min = rev_1 & 0xff;
 319
 320        ip_cfg = rev_2 & 0xff;
 321
 322        compat_len = sprintf(compat, "fsl,bman-portal-%u.%u.%u",
 323                             maj, min, ip_cfg) + 1;
 324        compat_len += sprintf(compat + compat_len, "fsl,bman-portal") + 1;
 325
 326        off = fdt_node_offset_by_compatible(blob, -1, "fsl,bman-portal");
 327        while (off != -FDT_ERR_NOTFOUND) {
 328                err = fdt_setprop(blob, off, "compatible", compat, compat_len);
 329                if (err < 0) {
 330                        printf("ERROR: unable to create props for %s: %s\n",
 331                               fdt_get_name(blob, off, NULL),
 332                               fdt_strerror(err));
 333                        return;
 334                }
 335
 336                off = fdt_node_offset_by_compatible(blob, off,
 337                                                    "fsl,bman-portal");
 338        }
 339}
 340