uboot/arch/arm/cpu/armv8/fsl-layerscape/icid.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2018 NXP
   4 */
   5
   6#include <common.h>
   7#include <linux/libfdt.h>
   8#include <fdt_support.h>
   9
  10#include <asm/io.h>
  11#include <asm/processor.h>
  12#include <asm/arch-fsl-layerscape/fsl_icid.h>
  13#include <fsl_fman.h>
  14
  15static void set_icid(struct icid_id_table *tbl, int size)
  16{
  17        int i;
  18
  19        for (i = 0; i < size; i++)
  20                if (tbl[i].le)
  21                        out_le32((u32 *)(tbl[i].reg_addr), tbl[i].reg);
  22                else
  23                        out_be32((u32 *)(tbl[i].reg_addr), tbl[i].reg);
  24}
  25
  26#ifdef CONFIG_SYS_DPAA_FMAN
  27void set_fman_icids(struct fman_icid_id_table *tbl, int size)
  28{
  29        int i;
  30        ccsr_fman_t *fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
  31
  32        for (i = 0; i < size; i++) {
  33                out_be32(&fm->fm_bmi_common.fmbm_ppid[tbl[i].port_id - 1],
  34                         tbl[i].icid);
  35        }
  36}
  37#endif
  38
  39void set_icids(void)
  40{
  41        /* setup general icid offsets */
  42        set_icid(icid_tbl, icid_tbl_sz);
  43
  44#ifdef CONFIG_SYS_DPAA_FMAN
  45        set_fman_icids(fman_icid_tbl, fman_icid_tbl_sz);
  46#endif
  47}
  48
  49int fdt_set_iommu_prop(void *blob, int off, int smmu_ph, u32 *ids, int num_ids)
  50{
  51        int i, ret;
  52        u32 prop[8];
  53
  54        /*
  55         * Note: The "iommus" property definition mentions Stream IDs while
  56         * this code handles ICIDs. The current implementation assumes that
  57         * ICIDs and Stream IDs are equal.
  58         */
  59        for (i = 0; i < num_ids; i++) {
  60                prop[i * 2] = cpu_to_fdt32(smmu_ph);
  61                prop[i * 2 + 1] = cpu_to_fdt32(ids[i]);
  62        }
  63        ret = fdt_setprop(blob, off, "iommus",
  64                          prop, sizeof(u32) * num_ids * 2);
  65        if (ret) {
  66                printf("WARNING unable to set iommus: %s\n", fdt_strerror(ret));
  67                return ret;
  68        }
  69
  70        return 0;
  71}
  72
  73int fdt_fixup_icid_tbl(void *blob, int smmu_ph,
  74                       struct icid_id_table *tbl, int size)
  75{
  76        int i, err, off;
  77
  78        for (i = 0; i < size; i++) {
  79                if (!tbl[i].compat)
  80                        continue;
  81
  82                off = fdt_node_offset_by_compat_reg(blob,
  83                                                    tbl[i].compat,
  84                                                    tbl[i].compat_addr);
  85                if (off > 0) {
  86                        err = fdt_set_iommu_prop(blob, off, smmu_ph,
  87                                                 &tbl[i].id, 1);
  88                        if (err)
  89                                return err;
  90                } else {
  91                        printf("WARNING could not find node %s: %s.\n",
  92                               tbl[i].compat, fdt_strerror(off));
  93                }
  94        }
  95
  96        return 0;
  97}
  98
  99#ifdef CONFIG_SYS_DPAA_FMAN
 100int get_fman_port_icid(int port_id, struct fman_icid_id_table *tbl,
 101                       const int size)
 102{
 103        int i;
 104
 105        for (i = 0; i < size; i++) {
 106                if (tbl[i].port_id == port_id)
 107                        return tbl[i].icid;
 108        }
 109
 110        return -1;
 111}
 112
 113void fdt_fixup_fman_port_icid_by_compat(void *blob, int smmu_ph,
 114                                        const char *compat)
 115{
 116        int noff, len, icid;
 117        const u32 *prop;
 118
 119        noff = fdt_node_offset_by_compatible(blob, -1, compat);
 120        while (noff > 0) {
 121                prop = fdt_getprop(blob, noff, "cell-index", &len);
 122                if (!prop) {
 123                        printf("WARNING missing cell-index for fman port\n");
 124                        continue;
 125                }
 126                if (len != 4) {
 127                        printf("WARNING bad cell-index size for fman port\n");
 128                        continue;
 129                }
 130
 131                icid = get_fman_port_icid(fdt32_to_cpu(*prop),
 132                                          fman_icid_tbl, fman_icid_tbl_sz);
 133                if (icid < 0) {
 134                        printf("WARNING unknown ICID for fman port %d\n",
 135                               *prop);
 136                        continue;
 137                }
 138
 139                fdt_set_iommu_prop(blob, noff, smmu_ph, (u32 *)&icid, 1);
 140
 141                noff = fdt_node_offset_by_compatible(blob, noff, compat);
 142        }
 143}
 144
 145void fdt_fixup_fman_icids(void *blob, int smmu_ph)
 146{
 147        static const char * const compats[] = {
 148                "fsl,fman-v3-port-oh",
 149                "fsl,fman-v3-port-rx",
 150                "fsl,fman-v3-port-tx",
 151        };
 152        int i;
 153
 154        for (i = 0; i < ARRAY_SIZE(compats); i++)
 155                fdt_fixup_fman_port_icid_by_compat(blob, smmu_ph, compats[i]);
 156}
 157#endif
 158
 159int fdt_get_smmu_phandle(void *blob)
 160{
 161        int noff, smmu_ph;
 162
 163        noff = fdt_node_offset_by_compatible(blob, -1, "arm,mmu-500");
 164        if (noff < 0) {
 165                printf("WARNING failed to get smmu node: %s\n",
 166                       fdt_strerror(noff));
 167                return noff;
 168        }
 169
 170        smmu_ph = fdt_get_phandle(blob, noff);
 171        if (!smmu_ph) {
 172                smmu_ph = fdt_create_phandle(blob, noff);
 173                if (!smmu_ph) {
 174                        printf("WARNING failed to get smmu phandle\n");
 175                        return -1;
 176                }
 177        }
 178
 179        return smmu_ph;
 180}
 181
 182void fdt_fixup_icid(void *blob)
 183{
 184        int smmu_ph;
 185
 186        smmu_ph = fdt_get_smmu_phandle(blob);
 187        if (smmu_ph < 0)
 188                return;
 189
 190        fdt_fixup_icid_tbl(blob, smmu_ph, icid_tbl, icid_tbl_sz);
 191
 192#ifdef CONFIG_SYS_DPAA_FMAN
 193        fdt_fixup_fman_icids(blob, smmu_ph);
 194#endif
 195}
 196