[PATCH v2] ARM: l2c: parse cache properties from ePAPR definitions
Arnd Bergmann
arnd at arndb.de
Tue Sep 9 00:42:18 PDT 2014
On Tuesday 09 September 2014 09:10:33 Linus Walleij wrote:
> When both 'cache-size' and 'cache-sets' are specified for a L2 cache
> controller node, parse those properties and set up the
> set size based on which type of L2 cache controller we are using.
>
> Update the L2 cache controller Device Tree binding with the optional
> 'cache-size', 'cache-sets', 'cache-block-size' and 'cache-line-size'
> properties. These come from the ePAPR specification.
>
> Using the cache size, number of sets and cache line size we can
> calculate desired associativity of the L2 cache. This is done
> by the calculation:
>
> set size = cache size / sets
> ways = set size / line size
> way size = cache size / ways
> associativity = way size / line size
>
> This patch is an extended version based on the initial patch
> by Florian Fainelli.
>
> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
Looks much better!
> +static void __init l2x0_cache_size_of_parse(const struct device_node *np,
> + u32 *aux_val, u32 *aux_mask,
> + u32 max_set_size,
> + u32 max_associativity)
> +{
> + u32 mask = 0, val = 0;
> + u32 cache_size = 0, sets = 0;
> + u32 set_size = 0, set_size_bits = 1;
> + u32 ways = 0, way_size = 0;
> + u32 blocksize = 0;
> + u32 linesize = 0;
> + u32 assoc = 0;
> +
> + of_property_read_u32(np, "cache-size", &cache_size);
> + of_property_read_u32(np, "cache-sets", &sets);
> + of_property_read_u32(np, "cache-block-size", &blocksize);
> + of_property_read_u32(np, "cache-line-size", &linesize);
> +
> + if (!cache_size || !sets)
> + return;
I wonder if we should add another property here that tells
the OS to override the aux register setting for way-size
and associativity. In theory the properties above are meant
to be there for any cache, but I don't think we want to actually
re-compute the auxctrl register values based on this all the
time.
> + /* All these l2 caches have the same line = block size actually */
> + if (!linesize) {
> + if (blocksize) {
> + /* If linesize if not given, it is equal to blocksize */
> + linesize = blocksize;
> + } else {
> + /* Fall back to known size */
> + linesize = CACHE_LINE_SIZE;
> + }
> + }
Maybe add a warning for the last fallback?
> + /* This is the PL3x0 case */
> + if (max_associativity == 16 && (assoc != 8 && assoc != 16)) {
> + pr_err("L2C OF: cache setting yield illegal associativity\n");
> + pr_err("L2C OF: %d calculated, only 8 and 16 legal\n", assoc);
> + return;
> + }
I'd rather see another function argument for the minimum associativity
here. We have a few other cache controllers that are partially compatible
with l2x0 (tauros3, aurora, bcm11351) and one of these or one we might
add in the future could support a maximum of 16 but also some other sizes
below 8.
> + /*
> + * Special checks for the PL310 that only has two settings and
> + * cannot be set to fully associative.
> + */
> + if (max_associativity == 16) {
> + if (assoc == 16)
> + val |= L310_AUX_CTRL_ASSOCIATIVITY_16;
> + /* Else bit is left zero == 8 way associativity */
> + } else {
> + val |= (assoc << L2X0_AUX_CTRL_ASSOC_SHIFT);
> + }
What happens if we set the bit for assoc=8 on pl310? Is that
defined to be ignored or does it have to be zero?
> + switch (set_size >> 10) {
> + case 512:
> + set_size_bits = 6;
> + break;
> + case 256:
> + set_size_bits = 5;
> + break;
> + case 128:
> + set_size_bits = 4;
> + break;
> + case 64:
> + set_size_bits = 3;
> + break;
> + case 32:
> + set_size_bits = 2;
> + break;
> + case 16:
> + set_size_bits = 1;
> + break;
> + default:
> + pr_err("L2C OF: cache way size: %d KB is not mapped\n",
> + way_size);
> + break;
> + }
> +
> + /*
> + * The l2x0 TRMs call this size "way size" but that is incorrect:
> + * the thing being configured in these register bits is actually
> + * the cache set size, so the variable here has the right name
> + * but the register bit definitions following the TRM are not
> + * in archaic naming.
> + */
No, I think actually the comment and the variable name are wrong here,
and the TRM is right. I'm surprised you get the right results out of
this. The set_size should be a relatively small number, e.g. 256 bytes
in case of an 8-way associative cache with 32 byte lines. What is the
pr_debug output and the properties you pass in for your example system?
Arnd
More information about the linux-arm-kernel
mailing list