123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /*
- * Copyright (C) 2017 SiFive
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <linux/cacheinfo.h>
- #include <linux/cpu.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- static void ci_leaf_init(struct cacheinfo *this_leaf,
- struct device_node *node,
- enum cache_type type, unsigned int level)
- {
- this_leaf->level = level;
- this_leaf->type = type;
- /* not a sector cache */
- this_leaf->physical_line_partition = 1;
- /* TODO: Add to DTS */
- this_leaf->attributes =
- CACHE_WRITE_BACK
- | CACHE_READ_ALLOCATE
- | CACHE_WRITE_ALLOCATE;
- }
- static int __init_cache_level(unsigned int cpu)
- {
- struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
- struct device_node *np = of_cpu_device_node_get(cpu);
- int levels = 0, leaves = 0, level;
- if (of_property_read_bool(np, "cache-size"))
- ++leaves;
- if (of_property_read_bool(np, "i-cache-size"))
- ++leaves;
- if (of_property_read_bool(np, "d-cache-size"))
- ++leaves;
- if (leaves > 0)
- levels = 1;
- while ((np = of_find_next_cache_node(np))) {
- if (!of_device_is_compatible(np, "cache"))
- break;
- if (of_property_read_u32(np, "cache-level", &level))
- break;
- if (level <= levels)
- break;
- if (of_property_read_bool(np, "cache-size"))
- ++leaves;
- if (of_property_read_bool(np, "i-cache-size"))
- ++leaves;
- if (of_property_read_bool(np, "d-cache-size"))
- ++leaves;
- levels = level;
- }
- this_cpu_ci->num_levels = levels;
- this_cpu_ci->num_leaves = leaves;
- return 0;
- }
- static int __populate_cache_leaves(unsigned int cpu)
- {
- struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
- struct cacheinfo *this_leaf = this_cpu_ci->info_list;
- struct device_node *np = of_cpu_device_node_get(cpu);
- int levels = 1, level = 1;
- if (of_property_read_bool(np, "cache-size"))
- ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
- if (of_property_read_bool(np, "i-cache-size"))
- ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
- if (of_property_read_bool(np, "d-cache-size"))
- ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
- while ((np = of_find_next_cache_node(np))) {
- if (!of_device_is_compatible(np, "cache"))
- break;
- if (of_property_read_u32(np, "cache-level", &level))
- break;
- if (level <= levels)
- break;
- if (of_property_read_bool(np, "cache-size"))
- ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
- if (of_property_read_bool(np, "i-cache-size"))
- ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
- if (of_property_read_bool(np, "d-cache-size"))
- ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
- levels = level;
- }
- return 0;
- }
- DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
- DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
|