From patchwork Wed Sep 10 08:59:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 37187 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f72.google.com (mail-yh0-f72.google.com [209.85.213.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C583220293 for ; Wed, 10 Sep 2014 09:00:07 +0000 (UTC) Received: by mail-yh0-f72.google.com with SMTP id f73sf10521446yha.3 for ; Wed, 10 Sep 2014 02:00:07 -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=g0xfBsI0RK1sL3XGuymSchpiDC7n/VR2kfKpzQWb9Qs=; b=m5X5Xsw6anBjZ2KyV6ykhXJMhk7l3OFl7c4OatKqyeMEol9BZCa0eFUvY/p9tpUKah 9l+Lobzi+iDAQePokShVeqyvNTVzYlSdhY1Gkw9aNcooLsVi+7Yd6Mt5KMt6SfTDPiWV hgUoHWeKXwBYYd5YyQR0Nq73+qgMeqyXaU+mJmXqQ9FA09+9gTeIr4aEJF4sOugkzWit mvQ258AZzBIuBeT1ooRPE5U2WEAUHvYIQe0QWXUtFtKDHWNbMmtfQXeqJBzEiO9eJZRZ CBDiu08gMiFrcYksjYQLxtS07+qOjACZzW0Zr65C9xSJQVbmjTlNNtNXJJ+owEOaH/XV NVUg== X-Gm-Message-State: ALoCoQm9mjEcvJRfrfyr3r+q/YDpCDQIjChEiuXzj1sHkKLqXsoiUhKFb4qfjUGbBxNHJjlb4rDI X-Received: by 10.236.143.2 with SMTP id k2mr24675188yhj.18.1410339607615; Wed, 10 Sep 2014 02:00:07 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.95.50 with SMTP id h47ls2555179qge.43.gmail; Wed, 10 Sep 2014 02:00:07 -0700 (PDT) X-Received: by 10.52.38.134 with SMTP id g6mr16522002vdk.34.1410339607533; Wed, 10 Sep 2014 02:00:07 -0700 (PDT) Received: from mail-vc0-f180.google.com (mail-vc0-f180.google.com [209.85.220.180]) by mx.google.com with ESMTPS id f2si6137670vcy.28.2014.09.10.02.00.07 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Sep 2014 02:00:07 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.180 as permitted sender) client-ip=209.85.220.180; Received: by mail-vc0-f180.google.com with SMTP id hq11so109479vcb.11 for ; Wed, 10 Sep 2014 02:00:07 -0700 (PDT) X-Received: by 10.52.33.231 with SMTP id u7mr8725352vdi.54.1410339607390; Wed, 10 Sep 2014 02:00:07 -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 uj3csp405932vcb; Wed, 10 Sep 2014 02:00:06 -0700 (PDT) X-Received: by 10.68.213.6 with SMTP id no6mr36415062pbc.53.1410339606253; Wed, 10 Sep 2014 02:00:06 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x1si27062590pdn.12.2014.09.10.02.00.05 for ; Wed, 10 Sep 2014 02:00:06 -0700 (PDT) Received-SPF: none (google.com: linux-leds-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 S1751346AbaIJJAE (ORCPT ); Wed, 10 Sep 2014 05:00:04 -0400 Received: from mail-wi0-f171.google.com ([209.85.212.171]:47828 "EHLO mail-wi0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752095AbaIJI7k (ORCPT ); Wed, 10 Sep 2014 04:59:40 -0400 Received: by mail-wi0-f171.google.com with SMTP id hi2so5851786wib.4 for ; Wed, 10 Sep 2014 01:59:38 -0700 (PDT) X-Received: by 10.194.209.205 with SMTP id mo13mr1216139wjc.122.1410339578609; Wed, 10 Sep 2014 01:59:38 -0700 (PDT) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id r8sm17746110wjy.20.2014.09.10.01.59.36 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Sep 2014 01:59:37 -0700 (PDT) From: Linus Walleij To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, Arnd Bergmann , Russell King Cc: Pawel Moll , Mark Rutland , Marc Zyngier , Will Deacon , Rob Herring , Linus Walleij , Florian Fainelli Subject: [PATCH v3] ARM: l2c: parse cache properties from ePAPR definitions Date: Wed, 10 Sep 2014 10:59:32 +0200 Message-Id: <1410339572-23694-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 1.9.3 Sender: linux-leds-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-leds@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.180 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 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 | 147 +++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt index af527ee111c2..918b4489ab73 100644 --- a/Documentation/devicetree/bindings/arm/l2cc.txt +++ b/Documentation/devicetree/bindings/arm/l2cc.txt @@ -43,7 +43,17 @@ Optional properties: - arm,io-coherent : indicates that the system is operating in an hardware I/O coherent mode. Valid only when the arm,pl310-cache compatible string is used. +- arm,override-auxreg : this boolean property tells the OS implementation of + the l2cc driver code to override the default cache size, sets (and thus + associativity) settings from the auxilary control register. This is to be + used when the boot code does not set up these properties correctly. - 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..8b4e54e3e18c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -945,6 +945,115 @@ 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; + + if (!of_property_read_bool(np, "arm,override-auxreg")) + return; + + 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); + + switch (way_size >> 10) { + case 512: + way_size_bits = 6; + break; + case 256: + way_size_bits = 5; + break; + case 128: + way_size_bits = 4; + break; + case 64: + way_size_bits = 3; + break; + case 32: + way_size_bits = 2; + break; + case 16: + way_size_bits = 1; + break; + default: + pr_err("L2C OF: cache way size illegal: %dKB is not mapped\n", + way_size); + break; + } + + 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 +1061,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 +1084,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 +1140,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 +1167,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 = { @@ -1238,6 +1375,7 @@ static void __init aurora_of_parse(const struct device_node *np, { u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU; u32 mask = AURORA_ACR_REPLACEMENT_MASK; + u32 assoc; of_property_read_u32(np, "cache-id-part", &cache_id_part_number_from_dt); @@ -1250,6 +1388,15 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + 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;