linux/arch/riscv/kernel/cacheinfo.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2017 SiFive
   4 */
   5
   6#include <linux/cacheinfo.h>
   7#include <linux/cpu.h>
   8#include <linux/of.h>
   9#include <linux/of_device.h>
  10
  11static void ci_leaf_init(struct cacheinfo *this_leaf,
  12                         struct device_node *node,
  13                         enum cache_type type, unsigned int level)
  14{
  15        this_leaf->level = level;
  16        this_leaf->type = type;
  17}
  18
  19static int __init_cache_level(unsigned int cpu)
  20{
  21        struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
  22        struct device_node *np = of_cpu_device_node_get(cpu);
  23        struct device_node *prev = NULL;
  24        int levels = 0, leaves = 0, level;
  25
  26        if (of_property_read_bool(np, "cache-size"))
  27                ++leaves;
  28        if (of_property_read_bool(np, "i-cache-size"))
  29                ++leaves;
  30        if (of_property_read_bool(np, "d-cache-size"))
  31                ++leaves;
  32        if (leaves > 0)
  33                levels = 1;
  34
  35        prev = np;
  36        while ((np = of_find_next_cache_node(np))) {
  37                of_node_put(prev);
  38                prev = np;
  39                if (!of_device_is_compatible(np, "cache"))
  40                        break;
  41                if (of_property_read_u32(np, "cache-level", &level))
  42                        break;
  43                if (level <= levels)
  44                        break;
  45                if (of_property_read_bool(np, "cache-size"))
  46                        ++leaves;
  47                if (of_property_read_bool(np, "i-cache-size"))
  48                        ++leaves;
  49                if (of_property_read_bool(np, "d-cache-size"))
  50                        ++leaves;
  51                levels = level;
  52        }
  53
  54        of_node_put(np);
  55        this_cpu_ci->num_levels = levels;
  56        this_cpu_ci->num_leaves = leaves;
  57
  58        return 0;
  59}
  60
  61static int __populate_cache_leaves(unsigned int cpu)
  62{
  63        struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
  64        struct cacheinfo *this_leaf = this_cpu_ci->info_list;
  65        struct device_node *np = of_cpu_device_node_get(cpu);
  66        struct device_node *prev = NULL;
  67        int levels = 1, level = 1;
  68
  69        if (of_property_read_bool(np, "cache-size"))
  70                ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
  71        if (of_property_read_bool(np, "i-cache-size"))
  72                ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
  73        if (of_property_read_bool(np, "d-cache-size"))
  74                ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
  75
  76        prev = np;
  77        while ((np = of_find_next_cache_node(np))) {
  78                of_node_put(prev);
  79                prev = np;
  80                if (!of_device_is_compatible(np, "cache"))
  81                        break;
  82                if (of_property_read_u32(np, "cache-level", &level))
  83                        break;
  84                if (level <= levels)
  85                        break;
  86                if (of_property_read_bool(np, "cache-size"))
  87                        ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
  88                if (of_property_read_bool(np, "i-cache-size"))
  89                        ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
  90                if (of_property_read_bool(np, "d-cache-size"))
  91                        ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
  92                levels = level;
  93        }
  94        of_node_put(np);
  95
  96        return 0;
  97}
  98
  99DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
 100DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
 101