From patchwork Wed Sep 10 11:01:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 37193 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ie0-f197.google.com (mail-ie0-f197.google.com [209.85.223.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9946D20293 for ; Wed, 10 Sep 2014 11:01:38 +0000 (UTC) Received: by mail-ie0-f197.google.com with SMTP id lx4sf3309594iec.4 for ; Wed, 10 Sep 2014 04:01:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe; bh=eOuvIXAm5GYAiHYS2TqEgZRAdr3qf8iDE0RX0ccH66U=; b=HQ9LQfjDF506IMsyK8y8SUwFIMp4ggzH3CIqsupRTSfpL5WBA30hwfB6M0uhCtC25Q xhJH6wd8rvj2LoHDcu0FbixpLtlkaCOJK2hivt0ajKUTN5IZS2BIKSYT/Kzq/c+qRU4I ymIpWv55wnqiwMRtBm0mtu3iwZnyXe/XE5tK0GzqJB/P5bv1X4RCNNCAbufGmh/u/eiu YSKhNIblC8S7pOTGM9RB9WSvUXUfB7bnsnYSK4T575BnEwH/BBFHpvzfNWqwZeSfb4O4 lUZNpDfW7rprwgukSCJkJfjCuDTI4Q2MEKtWicEPGzQ7P9jRnO7mQ377ttH0JPAYmCKt zkvQ== X-Gm-Message-State: ALoCoQl1AycOQMH7ucvr11Zp25w893WP/g6GvYcsptUVIPhwDQNV4hcM6lQmsRnga1kZVd5eVwVB X-Received: by 10.42.207.146 with SMTP id fy18mr25400436icb.12.1410346898217; Wed, 10 Sep 2014 04:01:38 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.89.231 with SMTP id v94ls2525385qgd.14.gmail; Wed, 10 Sep 2014 04:01:38 -0700 (PDT) X-Received: by 10.220.168.210 with SMTP id v18mr4874829vcy.3.1410346898120; Wed, 10 Sep 2014 04:01:38 -0700 (PDT) Received: from mail-vc0-f172.google.com (mail-vc0-f172.google.com [209.85.220.172]) by mx.google.com with ESMTPS id em3si6779837vdc.61.2014.09.10.04.01.38 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Sep 2014 04:01:38 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.172 as permitted sender) client-ip=209.85.220.172; Received: by mail-vc0-f172.google.com with SMTP id hy10so4703674vcb.3 for ; Wed, 10 Sep 2014 04:01:38 -0700 (PDT) X-Received: by 10.52.69.195 with SMTP id g3mr12460950vdu.45.1410346897914; Wed, 10 Sep 2014 04:01:37 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp419155vcb; Wed, 10 Sep 2014 04:01:37 -0700 (PDT) X-Received: by 10.66.141.197 with SMTP id rq5mr37093696pab.124.1410346896924; Wed, 10 Sep 2014 04:01:36 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id sp10si27326467pab.94.2014.09.10.04.01.36 for ; Wed, 10 Sep 2014 04:01:36 -0700 (PDT) Received-SPF: none (google.com: devicetree-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752498AbaIJLBf (ORCPT + 5 others); Wed, 10 Sep 2014 07:01:35 -0400 Received: from mail-we0-f170.google.com ([74.125.82.170]:57093 "EHLO mail-we0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752480AbaIJLBe (ORCPT ); Wed, 10 Sep 2014 07:01:34 -0400 Received: by mail-we0-f170.google.com with SMTP id u57so5201182wes.29 for ; Wed, 10 Sep 2014 04:01:32 -0700 (PDT) X-Received: by 10.194.78.100 with SMTP id a4mr2329598wjx.106.1410346892883; Wed, 10 Sep 2014 04:01:32 -0700 (PDT) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id ll20sm2006624wic.14.2014.09.10.04.01.31 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Sep 2014 04:01:31 -0700 (PDT) From: Linus Walleij To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, Arnd Bergmann , Russell King Cc: Pawel Moll , Mark Rutland , Marc Zyngier , Will Deacon , Rob Herring , Linus Walleij , Florian Fainelli Subject: [PATCH v4] ARM: l2c: parse cache properties from ePAPR definitions Date: Wed, 10 Sep 2014 13:01:27 +0200 Message-Id: <1410346887-9195-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 1.9.3 Sender: devicetree-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: devicetree@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linus.walleij@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.172 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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 = sets * line size associativity = cache size / way size Example output from the PB1176 DT that look like this: L2: l2-cache { compatible = "arm,l220-cache"; (...) arm,override-auxreg; cache-size = <131072>; // 128kB cache-sets = <512>; cache-line-size = <32>; }; Ends up like this: L2C OF: override cache size: 131072 bytes (128KB) L2C OF: override line size: 32 bytes L2C OF: override way size: 16384 bytes (16KB) L2C OF: override associativity: 8 L2C: DT/platform modifies aux control register: 0x02020fff -> 0x02030fff L2C-220 cache controller enabled, 8 ways, 128 kB L2C-220: CACHE_ID 0x41000486, AUX_CTRL 0x06030fff Which is consistent with the value earlier hardcoded for the PB1176 platform. This patch is an extended version based on the initial patch by Florian Fainelli. Signed-off-by: Florian Fainelli Signed-off-by: Linus Walleij --- ChangeLog v3->v4: - Cut the boolean device tree property to specify whether the auxilary register should be overridden: always override of these properties are present. - Add a pointer to the ePAPR v1.1 specification to the L2C device tree bindings document. - Delete the Aurora support: this l2 cache have different ways of handling bits and pieces and need a specially rewritten piece of support code. Let's assume these caches do not need to be augmented from the device tree. - Use ilog2() to calculate the way size bit field. ChangeLog v2->v3: - Fix up way size and associativity calculations using the combined wisdom of Arnd and Russell. - Push associativity writes down to each cache hardware implementation, L2x0/PL3x0 respectively. - Introduce a boolean device tree property to tell whether the auxilary register value containing these size and set-based configurations should be modified by the OS or not --- Documentation/devicetree/bindings/arm/l2cc.txt | 10 ++ arch/arm/mm/cache-l2x0.c | 121 +++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt index af527ee111c2..292ef7ca3058 100644 --- a/Documentation/devicetree/bindings/arm/l2cc.txt +++ b/Documentation/devicetree/bindings/arm/l2cc.txt @@ -2,6 +2,10 @@ ARM cores often have a separate level 2 cache controller. There are various implementations of the L2 cache controller with compatible programming models. +Some of the properties that are just prefixed "cache-*" are taken from section +3.7.3 of the ePAPR v1.1 specification which can be found at: +https://www.power.org/wp-content/uploads/2012/06/Power_ePAPR_APPROVED_v1.1.pdf + The ARM L2 cache representation in the device tree should be done as follows: Required properties: @@ -44,6 +48,12 @@ Optional properties: I/O coherent mode. Valid only when the arm,pl310-cache compatible string is used. - interrupts : 1 combined interrupt. +- cache-size : specifies the size in bytes of the cache +- cache-sets : specifies the number of associativity sets of the cache +- cache-block-size : specifies the size in bytes of a cache block +- cache-line-size : specifies the size in bytes of a line in the cache, + if this is not specified, the line size is assumed to be equal to the + cache block size - cache-id-part: cache id part number to be used if it is not present on hardware - wt-override: If present then L2 is forced to Write through mode diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 5f2c988a06ac..55f9d6e0cc88 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -945,6 +946,98 @@ static int l2_wt_override; * pass it though the device tree */ static u32 cache_id_part_number_from_dt; +/** + * l2x0_cache_size_of_parse() - read cache size parameters from DT + * @np: the device tree node for the l2 cache + * @aux_val: pointer to machine-supplied auxilary register value, to + * be augmented by the call (bits to be set to 1) + * @aux_mask: pointer to machine-supplied auxilary register mask, to + * be augmented by the call (bits to be set to 0) + * @associativity: variable to return the calculated associativity in + * @max_way_size: the maximum size in bytes for the cache ways + */ +static void __init l2x0_cache_size_of_parse(const struct device_node *np, + u32 *aux_val, u32 *aux_mask, + u32 *associativity, + u32 max_way_size) +{ + u32 mask = 0, val = 0; + u32 cache_size = 0, sets = 0; + u32 way_size_bits = 1; + u32 way_size = 0; + u32 block_size = 0; + u32 line_size = 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", &block_size); + of_property_read_u32(np, "cache-line-size", &line_size); + + if (!cache_size || !sets) + return; + + /* All these l2 caches have the same line = block size actually */ + if (!line_size) { + if (block_size) { + /* If linesize if not given, it is equal to blocksize */ + line_size = block_size; + } else { + /* Fall back to known size */ + pr_warn("L2C OF: no cache block/line size given: " + "falling back to default size %d bytes\n", + CACHE_LINE_SIZE); + line_size = CACHE_LINE_SIZE; + } + } + + if (line_size != CACHE_LINE_SIZE) + pr_warn("L2C OF: DT supplied line size %d bytes does " + "not match hardware line size of %d bytes\n", + line_size, + CACHE_LINE_SIZE); + + /* + * Since: + * set size = cache size / sets + * ways = cache size / (sets * line size) + * way size = cache size / (cache size / (sets * line size)) + * way size = sets * line size + * associativity = ways = cache size / way size + */ + way_size = sets * line_size; + *associativity = cache_size / way_size; + + if (way_size > max_way_size) { + pr_err("L2C OF: set size %dKB is too large\n", way_size); + return; + } + + pr_info("L2C OF: override cache size: %d bytes (%dKB)\n", + cache_size, cache_size >> 10); + pr_info("L2C OF: override line size: %d bytes\n", line_size); + pr_info("L2C OF: override way size: %d bytes (%dKB)\n", + way_size, way_size >> 10); + pr_info("L2C OF: override associativity: %d\n", *associativity); + + /* + * Calculates the bits 17:19 to set for way size: + * 512KB -> 6, 256KB -> 5, ... 16KB -> 1 + */ + way_size_bits = ilog2(way_size >> 10) - 3; + if (way_size_bits < 1 || way_size_bits > 6) { + pr_err("L2C OF: cache way size illegal: %dKB is not mapped\n", + way_size); + return; + } + + mask |= L2C_AUX_CTRL_WAY_SIZE_MASK; + val |= (way_size_bits << L2C_AUX_CTRL_WAY_SIZE_SHIFT); + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + static void __init l2x0_of_parse(const struct device_node *np, u32 *aux_val, u32 *aux_mask) { @@ -952,6 +1045,7 @@ static void __init l2x0_of_parse(const struct device_node *np, u32 tag = 0; u32 dirty = 0; u32 val = 0, mask = 0; + u32 assoc; of_property_read_u32(np, "arm,tag-latency", &tag); if (tag) { @@ -974,6 +1068,15 @@ static void __init l2x0_of_parse(const struct device_node *np, val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; } + l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_256K); + if (assoc > 8) { + pr_err("l2x0 of: cache setting yield too high associativity\n"); + pr_err("l2x0 of: %d calculated, max 8\n", assoc); + } else { + mask |= L2X0_AUX_CTRL_ASSOC_MASK; + val |= (assoc << L2X0_AUX_CTRL_ASSOC_SHIFT); + } + *aux_val &= ~mask; *aux_val |= val; *aux_mask &= ~mask; @@ -1021,6 +1124,7 @@ static void __init l2c310_of_parse(const struct device_node *np, u32 data[3] = { 0, 0, 0 }; u32 tag[3] = { 0, 0, 0 }; u32 filter[2] = { 0, 0 }; + u32 assoc; of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); if (tag[0] && tag[1] && tag[2]) @@ -1047,6 +1151,23 @@ static void __init l2c310_of_parse(const struct device_node *np, writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN, l2x0_base + L310_ADDR_FILTER_START); } + + l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K); + switch (assoc) { + case 16: + *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK; + *aux_val |= L310_AUX_CTRL_ASSOCIATIVITY_16; + *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK; + break; + case 8: + *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK; + *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK; + break; + default: + pr_err("PL310 OF: cache setting yield illegal associativity\n"); + pr_err("PL310 OF: %d calculated, only 8 and 16 legal\n", assoc); + break; + } } static const struct l2c_init_data of_l2c310_data __initconst = {