dpdk/drivers/common/cnxk/roc_model.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(C) 2021 Marvell.
   3 */
   4
   5#include "roc_api.h"
   6#include "roc_priv.h"
   7
   8struct roc_model *roc_model;
   9
  10/* RoC and CPU IDs and revisions */
  11#define VENDOR_ARM    0x41 /* 'A' */
  12#define VENDOR_CAVIUM 0x43 /* 'C' */
  13
  14#define SOC_PART_CN10K 0xD49
  15
  16#define PART_106XX  0xB9
  17#define PART_105XX  0xBA
  18#define PART_105XXN 0xBC
  19#define PART_98XX   0xB1
  20#define PART_96XX   0xB2
  21#define PART_95XX   0xB3
  22#define PART_95XXN  0xB4
  23#define PART_95XXMM 0xB5
  24#define PART_95O    0xB6
  25
  26#define MODEL_IMPL_BITS   8
  27#define MODEL_IMPL_SHIFT  24
  28#define MODEL_IMPL_MASK   ((1 << MODEL_IMPL_BITS) - 1)
  29#define MODEL_PART_BITS   12
  30#define MODEL_PART_SHIFT  4
  31#define MODEL_PART_MASK   ((1 << MODEL_PART_BITS) - 1)
  32#define MODEL_MAJOR_BITS  4
  33#define MODEL_MAJOR_SHIFT 20
  34#define MODEL_MAJOR_MASK  ((1 << MODEL_MAJOR_BITS) - 1)
  35#define MODEL_MINOR_BITS  4
  36#define MODEL_MINOR_SHIFT 0
  37#define MODEL_MINOR_MASK  ((1 << MODEL_MINOR_BITS) - 1)
  38
  39static const struct model_db {
  40        uint32_t impl;
  41        uint32_t part;
  42        uint32_t major;
  43        uint32_t minor;
  44        uint64_t flag;
  45        char name[ROC_MODEL_STR_LEN_MAX];
  46} model_db[] = {
  47        {VENDOR_ARM, PART_106XX, 0, 0, ROC_MODEL_CN106XX, "cn10ka"},
  48        {VENDOR_ARM, PART_105XX, 0, 0, ROC_MODEL_CNF105XX, "cnf10ka"},
  49        {VENDOR_ARM, PART_105XXN, 0, 0, ROC_MODEL_CNF105XXN, "cnf10kb"},
  50        {VENDOR_CAVIUM, PART_98XX, 0, 0, ROC_MODEL_CN98xx_A0, "cn98xx_a0"},
  51        {VENDOR_CAVIUM, PART_96XX, 0, 0, ROC_MODEL_CN96xx_A0, "cn96xx_a0"},
  52        {VENDOR_CAVIUM, PART_96XX, 0, 1, ROC_MODEL_CN96xx_B0, "cn96xx_b0"},
  53        {VENDOR_CAVIUM, PART_96XX, 2, 0, ROC_MODEL_CN96xx_C0, "cn96xx_c0"},
  54        {VENDOR_CAVIUM, PART_95XX, 0, 0, ROC_MODEL_CNF95xx_A0, "cnf95xx_a0"},
  55        {VENDOR_CAVIUM, PART_95XX, 1, 0, ROC_MODEL_CNF95xx_B0, "cnf95xx_b0"},
  56        {VENDOR_CAVIUM, PART_95XXN, 0, 0, ROC_MODEL_CNF95XXN_A0, "cnf95xxn_a0"},
  57        {VENDOR_CAVIUM, PART_95O, 0, 0, ROC_MODEL_CNF95XXO_A0, "cnf95O_a0"},
  58        {VENDOR_CAVIUM, PART_95XXMM, 0, 0, ROC_MODEL_CNF95XXMM_A0,
  59         "cnf95xxmm_a0"}
  60};
  61
  62static uint32_t
  63cn10k_part_get(void)
  64{
  65        uint32_t soc = 0x0;
  66        char buf[BUFSIZ];
  67        char *ptr;
  68        FILE *fd;
  69
  70        /* Read the CPU compatible variant */
  71        fd = fopen("/proc/device-tree/compatible", "r");
  72        if (!fd) {
  73                plt_err("Failed to open /proc/device-tree/compatible");
  74                goto err;
  75        }
  76
  77        if (fgets(buf, sizeof(buf), fd) == NULL) {
  78                plt_err("Failed to read from /proc/device-tree/compatible");
  79                goto fclose;
  80        }
  81        ptr = strchr(buf, ',');
  82        if (!ptr) {
  83                plt_err("Malformed 'CPU compatible': <%s>", buf);
  84                goto fclose;
  85        }
  86        ptr++;
  87        if (strcmp("cn10ka", ptr) == 0) {
  88                soc = PART_106XX;
  89        } else if (strcmp("cnf10ka", ptr) == 0) {
  90                soc = PART_105XX;
  91        } else if (strcmp("cnf10kb", ptr) == 0) {
  92                soc = PART_105XXN;
  93        } else {
  94                plt_err("Unidentified 'CPU compatible': <%s>", ptr);
  95                goto fclose;
  96        }
  97
  98fclose:
  99        fclose(fd);
 100
 101err:
 102        return soc;
 103}
 104
 105static bool
 106populate_model(struct roc_model *model, uint32_t midr)
 107{
 108        uint32_t impl, major, part, minor;
 109        bool found = false;
 110        size_t i;
 111
 112        impl = (midr >> MODEL_IMPL_SHIFT) & MODEL_IMPL_MASK;
 113        part = (midr >> MODEL_PART_SHIFT) & MODEL_PART_MASK;
 114        major = (midr >> MODEL_MAJOR_SHIFT) & MODEL_MAJOR_MASK;
 115        minor = (midr >> MODEL_MINOR_SHIFT) & MODEL_MINOR_MASK;
 116
 117        /* Update part number for cn10k from device-tree */
 118        if (part == SOC_PART_CN10K)
 119                part = cn10k_part_get();
 120
 121        for (i = 0; i < PLT_DIM(model_db); i++)
 122                if (model_db[i].impl == impl && model_db[i].part == part &&
 123                    model_db[i].major == major && model_db[i].minor == minor) {
 124                        model->flag = model_db[i].flag;
 125                        strncpy(model->name, model_db[i].name,
 126                                ROC_MODEL_STR_LEN_MAX - 1);
 127                        found = true;
 128                        break;
 129                }
 130
 131        if (!found) {
 132                model->flag = 0;
 133                strncpy(model->name, "unknown", ROC_MODEL_STR_LEN_MAX - 1);
 134                plt_err("Invalid RoC model (impl=0x%x, part=0x%x)", impl, part);
 135        }
 136
 137        return found;
 138}
 139
 140static int
 141midr_get(unsigned long *val)
 142{
 143        const char *file =
 144                "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1";
 145        int rc = UTIL_ERR_FS;
 146        char buf[BUFSIZ];
 147        char *end = NULL;
 148        FILE *f;
 149
 150        if (val == NULL)
 151                goto err;
 152        f = fopen(file, "r");
 153        if (f == NULL)
 154                goto err;
 155
 156        if (fgets(buf, sizeof(buf), f) == NULL)
 157                goto fclose;
 158
 159        *val = strtoul(buf, &end, 0);
 160        if ((buf[0] == '\0') || (end == NULL) || (*end != '\n'))
 161                goto fclose;
 162
 163        rc = 0;
 164fclose:
 165        fclose(f);
 166err:
 167        return rc;
 168}
 169
 170static void
 171detect_invalid_config(void)
 172{
 173#ifdef ROC_PLATFORM_CN9K
 174#ifdef ROC_PLATFORM_CN10K
 175        PLT_STATIC_ASSERT(0);
 176#endif
 177#endif
 178}
 179
 180int
 181roc_model_init(struct roc_model *model)
 182{
 183        int rc = UTIL_ERR_PARAM;
 184        unsigned long midr;
 185
 186        detect_invalid_config();
 187
 188        if (!model)
 189                goto err;
 190
 191        rc = midr_get(&midr);
 192        if (rc)
 193                goto err;
 194
 195        rc = UTIL_ERR_INVALID_MODEL;
 196        if (!populate_model(model, midr))
 197                goto err;
 198
 199        rc = 0;
 200        plt_info("RoC Model: %s", model->name);
 201        roc_model = model;
 202err:
 203        return rc;
 204}
 205