Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp785023rwl; Wed, 12 Apr 2023 04:13:11 -0700 (PDT) X-Google-Smtp-Source: AKy350acqPw+oic38tvWXYswQg+XoQnI0BPmxyey3PUaxCpAczJBPLBZeMSE/oIqsOZCWf0wSWxm X-Received: by 2002:a17:902:db01:b0:1a1:f5dd:2dce with SMTP id m1-20020a170902db0100b001a1f5dd2dcemr8037314plx.6.1681297991097; Wed, 12 Apr 2023 04:13:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681297991; cv=none; d=google.com; s=arc-20160816; b=OpF5lvZRHVwHTEJOE3nVjMYPKSivZBt5Bb4mjM8Sy0ioaK08cmTECYJlF9g7NKWwLN riiPn6ExmCfh00SfA5xcU5dbVMuPSLe1LoAYTM1RCbLbBgp0EQGs/Qy/NbT27Wpe4nZF BFacZ55f7BLyfgEd/mz1rLYB1lA63sVd8uEAInVakd4mw3HjOfUk2Ym0vVS26+gPkkML F0OvVW1hmGYfFan9J/wXM/9Pn56tOi5+tTL1S4zFJpS699QDCnAK9tHpdhlc6Zx0YMLg 9zw1KOFmqSDLBYUsuz3UTXxWSyReutstMGRhI6YO6zoH5ljkjBfg0PR90L8E7u0TEUwZ pqGQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=qNB/LQ+2e9RHIyw+KYF13k6Gi/pRgp/ViMk5z3IzBHc=; b=D9XRVTRL7kwiZA1/JWzk0lf08GASArSXDB/PfJNkZC9HL8vhQ36+eDJfuj0DxnXrr2 x7cFu3gCsoiFQNIvkIJjAXq568+n7rrxHoWK+osH+sWpvp1ut5S+j5QIrm+iLnZ7Hmjp 6yB01vhs41vyNCHza9s3tczc3w6IYl63hiVPnCgSOrWmCZaW+704/1nHLrx4tZemBxCc s6OUfCqnVO7YRauPelz/cHTObPL/MSdVxSv06zi2o3UdgEfRS5vfoHgs+C2zy5aGwU5e Llwf8AqB38PVsaDkuBO6jDLijCCIXxP9LYXh33B3J8d0DRJzP7paFhZiaZuRidi2BIN4 6sfg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=WQ69rz8q; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z11-20020a6552cb000000b004fb171df693si15251045pgp.352.2023.04.12.04.12.59; Wed, 12 Apr 2023 04:13:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=WQ69rz8q; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229747AbjDLLJx (ORCPT + 99 others); Wed, 12 Apr 2023 07:09:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229477AbjDLLJi (ORCPT ); Wed, 12 Apr 2023 07:09:38 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A50A940F2; Wed, 12 Apr 2023 04:09:31 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id j11so14123852wrd.2; Wed, 12 Apr 2023 04:09:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1681297770; x=1683889770; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qNB/LQ+2e9RHIyw+KYF13k6Gi/pRgp/ViMk5z3IzBHc=; b=WQ69rz8q6X+JyFAUjanXhwu/mRXMiyt7GZGBGt7XH1QHkiERrN8f3ABhNmldinKAlq dg9iT14yNwIkFbiXbbPX0w16xP9yP4R6vVRefM3bYBusGVhqLx9f7NgSZXEt6hJHJtEI EakYmLp3foSOHOZplcghljf2jdy582o0eF5G5bitDM9Mg9zt7P0f0CBuFhytkEnfZcVX mRvQH0qFPuJtx9wxWZjiM1C4NDIlbcI3AU1F6l88Me6xrycml/YlqplzGD+MgmwND5gU k2dnDI7a/H4Dy9GNjOd3SmsXbov89Rvfe4wpni5YERHQeuydytgauVV/kBpAT4cfgoQB kx4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681297770; x=1683889770; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qNB/LQ+2e9RHIyw+KYF13k6Gi/pRgp/ViMk5z3IzBHc=; b=PE4pjIelmQpiQmkR/+L0uGZqjxi7r65AG1tL2JMk4HtZrMEZwu+xWQ7Go52YPDl8TI B5srf2ADhKLupZHUIWkVzTYZfphMtFtPcpt4NdFtnXXfjWd88wVbaeHpiY7dKYI6oUAo HEnhkt7Plt43MubPLR/Oq8muXJ3lF+jjoIk9T/dfrQzQWt2hdTF8CjlRyPhEvisAYrFu ABHemi4D0rpyyl7sLuf8ThBc6ipbyaXRC4wy3kkD36Z2Rb4QztsSbi7EUh3vMSkKeVVS I5FW8AcIbO3aR7WtPkA38vBU3nBlJYMqzrDRMZeWpsjsvFhUBFSHZObuwxNsChc4gbF5 AuMg== X-Gm-Message-State: AAQBX9f8y+z6Y7hkTdkeLoFaNMXOGVPm4PERYklxhGbx/0dCewRkUGSr 5Bu2X/KzQB4Ji9opz+iIY4E= X-Received: by 2002:a5d:6e03:0:b0:2f2:7e53:db65 with SMTP id h3-20020a5d6e03000000b002f27e53db65mr1779957wrz.7.1681297770072; Wed, 12 Apr 2023 04:09:30 -0700 (PDT) Received: from prasmi.home ([2a00:23c8:2501:c701:783d:9280:20c4:db22]) by smtp.gmail.com with ESMTPSA id l13-20020a5d668d000000b002e61e002943sm16863582wru.116.2023.04.12.04.09.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Apr 2023 04:09:29 -0700 (PDT) From: Prabhakar X-Google-Original-From: Prabhakar To: Arnd Bergmann , Conor Dooley , Geert Uytterhoeven , Heiko Stuebner , Guo Ren , Andrew Jones , Paul Walmsley , Palmer Dabbelt , Albert Ou , Samuel Holland , linux-riscv@lists.infradead.org Cc: Rob Herring , Krzysztof Kozlowski , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Prabhakar , Biju Das , Lad Prabhakar Subject: [PATCH v8 5/7] cache: Add L2 cache management for Andes AX45MP RISC-V core Date: Wed, 12 Apr 2023 12:08:58 +0100 Message-Id: <20230412110900.69738-6-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230412110900.69738-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20230412110900.69738-1-prabhakar.mahadev-lad.rj@bp.renesas.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lad Prabhakar I/O Coherence Port (IOCP) provides an AXI interface for connecting external non-caching masters, such as DMA controllers. The accesses from IOCP are coherent with D-Caches and L2 Cache. IOCP is a specification option and is disabled on the Renesas RZ/Five SoC due to this reason IP blocks using DMA will fail. The Andes AX45MP core has a Programmable Physical Memory Attributes (PMA) block that allows dynamic adjustment of memory attributes in the runtime. It contains a configurable amount of PMA entries implemented as CSR registers to control the attributes of memory locations in interest. Below are the memory attributes supported: * Device, Non-bufferable * Device, bufferable * Memory, Non-cacheable, Non-bufferable * Memory, Non-cacheable, Bufferable * Memory, Write-back, No-allocate * Memory, Write-back, Read-allocate * Memory, Write-back, Write-allocate * Memory, Write-back, Read and Write-allocate More info about PMA (section 10.3): Link: http://www.andestech.com/wp-content/uploads/AX45MP-1C-Rev.-5.0.0-Datasheet.pdf As a workaround for SoCs with IOCP disabled CMO needs to be handled by software. Firstly OpenSBI configures the memory region as "Memory, Non-cacheable, Bufferable" and passes this region as a global shared dma pool as a DT node. With DMA_GLOBAL_POOL enabled all DMA allocations happen from this region and synchronization callbacks are implemented to synchronize when doing DMA transactions. Example PMA region passes as a DT node from OpenSBI: reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; pma_resv0@58000000 { compatible = "shared-dma-pool"; reg = <0x0 0x58000000 0x0 0x08000000>; no-map; linux,dma-default; }; }; Signed-off-by: Lad Prabhakar --- v7 -> v8 * Dropped function pointer usage * Now exporting the functions for clean/inval/flush * Switched to using early_initcall instead of arch_initcall * Dropped entry for "include/cache" from MAINTAINERS * Dropped dependency of RISCV on AX45MP_L2_CACHE * Returning error in case of cache line mismatch * Renamed clean/inval/flush functions v6 -> v7 * Implemented flush callback * Dropped using riscv_dma_noncoherent_cmo_ops v5 -> v6 * Moved driver to cache folder * Switched to new API for CMO v4 -> v5 * Dropped code for configuring L2 cache * Dropped code for configuring PMA * Updated commit message * Added comments * Changed static branch enable/disable order RFC v3 -> v4 * Made use of runtime patching instead of compile time * Now just exposing single function ax45mp_no_iocp_cmo() for CMO handling * Added a check to make sure cache line size is always 64 bytes * Renamed folder rzf -> rzfive * Improved Kconfig description * Dropped L2 cache configuration * Dropped unnecessary casts * Fixed comments pointed by Geert. --- MAINTAINERS | 7 ++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/cache/Kconfig | 10 ++ drivers/cache/Makefile | 3 + drivers/cache/ax45mp_cache.c | 222 +++++++++++++++++++++++++++++++++++ 6 files changed, 245 insertions(+) create mode 100644 drivers/cache/Kconfig create mode 100644 drivers/cache/Makefile create mode 100644 drivers/cache/ax45mp_cache.c diff --git a/MAINTAINERS b/MAINTAINERS index 3afd45f71043..9afd39a23524 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19898,6 +19898,13 @@ S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git F: drivers/staging/ +STANDALONE CACHE CONTROLLER DRIVERS +M: Conor Dooley +L: linux-riscv@lists.infradead.org +S: Maintained +T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ +F: drivers/cache + STARFIRE/DURALAN NETWORK DRIVER M: Ion Badulescu S: Odd Fixes diff --git a/drivers/Kconfig b/drivers/Kconfig index 968bd0a6fd78..44abd2cba3a3 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -15,6 +15,8 @@ source "drivers/base/Kconfig" source "drivers/bus/Kconfig" +source "drivers/cache/Kconfig" + source "drivers/connector/Kconfig" source "drivers/firmware/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 20b118dca999..db5a8115093f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -11,6 +11,7 @@ ifdef building_out_of_srctree MAKEFLAGS += --include-dir=$(srctree) endif +obj-y += cache/ obj-y += irqchip/ obj-y += bus/ diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig new file mode 100644 index 000000000000..b97269cbd149 --- /dev/null +++ b/drivers/cache/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +menu "Cache Drivers" + +config AX45MP_L2_CACHE + bool "Andes Technology AX45MP L2 Cache controller" + depends on RISCV_DMA_NONCOHERENT + help + Support for the L2 cache controller on Andes Technology AX45MP platforms. + +endmenu diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile new file mode 100644 index 000000000000..2012e7fb978d --- /dev/null +++ b/drivers/cache/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o diff --git a/drivers/cache/ax45mp_cache.c b/drivers/cache/ax45mp_cache.c new file mode 100644 index 000000000000..cfc40b967c55 --- /dev/null +++ b/drivers/cache/ax45mp_cache.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * non-coherent cache functions for Andes AX45MP + * + * Copyright (C) 2023 Renesas Electronics Corp. + */ + +#include +#include +#include +#include +#include + +/* L2 cache registers */ +#define AX45MP_L2C_REG_CTL_OFFSET 0x8 + +#define AX45MP_L2C_REG_C0_CMD_OFFSET 0x40 +#define AX45MP_L2C_REG_C0_ACC_OFFSET 0x48 +#define AX45MP_L2C_REG_STATUS_OFFSET 0x80 + +/* D-cache operation */ +#define AX45MP_CCTL_L1D_VA_INVAL 0 /* Invalidate an L1 cache entry */ +#define AX45MP_CCTL_L1D_VA_WB 1 /* Write-back an L1 cache entry */ + +/* L2 CCTL status */ +#define AX45MP_CCTL_L2_STATUS_IDLE 0 + +/* L2 CCTL status cores mask */ +#define AX45MP_CCTL_L2_STATUS_C0_MASK 0xf + +/* L2 cache operation */ +#define AX45MP_CCTL_L2_PA_INVAL 0x8 /* Invalidate an L2 cache entry */ +#define AX45MP_CCTL_L2_PA_WB 0x9 /* Write-back an L2 cache entry */ + +#define AX45MP_L2C_REG_PER_CORE_OFFSET 0x10 +#define AX45MP_CCTL_L2_STATUS_PER_CORE_OFFSET 4 + +#define AX45MP_L2C_REG_CN_CMD_OFFSET(n) \ + (AX45MP_L2C_REG_C0_CMD_OFFSET + ((n) * AX45MP_L2C_REG_PER_CORE_OFFSET)) +#define AX45MP_L2C_REG_CN_ACC_OFFSET(n) \ + (AX45MP_L2C_REG_C0_ACC_OFFSET + ((n) * AX45MP_L2C_REG_PER_CORE_OFFSET)) +#define AX45MP_CCTL_L2_STATUS_CN_MASK(n) \ + (AX45MP_CCTL_L2_STATUS_C0_MASK << ((n) * AX45MP_CCTL_L2_STATUS_PER_CORE_OFFSET)) + +#define AX45MP_CCTL_REG_UCCTLBEGINADDR_NUM 0x80b +#define AX45MP_CCTL_REG_UCCTLCOMMAND_NUM 0x80c + +#define AX45MP_CACHE_LINE_SIZE 64 + +struct ax45mp_priv { + void __iomem *l2c_base; + u32 ax45mp_cache_line_size; +}; + +static struct ax45mp_priv ax45mp_priv; + +/* L2 Cache operations */ +static inline uint32_t ax45mp_cpu_l2c_get_cctl_status(void) +{ + return readl(ax45mp_priv.l2c_base + AX45MP_L2C_REG_STATUS_OFFSET); +} + +static void ax45mp_cpu_cache_operation(unsigned long start, unsigned long end, + unsigned long line_size, unsigned int l1_op, + unsigned int l2_op) +{ + void __iomem *base = ax45mp_priv.l2c_base; + int mhartid = smp_processor_id(); + unsigned long pa; + + while (end > start) { + csr_write(AX45MP_CCTL_REG_UCCTLBEGINADDR_NUM, start); + csr_write(AX45MP_CCTL_REG_UCCTLCOMMAND_NUM, l1_op); + + pa = virt_to_phys((void *)start); + writel(pa, base + AX45MP_L2C_REG_CN_ACC_OFFSET(mhartid)); + writel(l2_op, base + AX45MP_L2C_REG_CN_CMD_OFFSET(mhartid)); + while ((ax45mp_cpu_l2c_get_cctl_status() & + AX45MP_CCTL_L2_STATUS_CN_MASK(mhartid)) != + AX45MP_CCTL_L2_STATUS_IDLE) + ; + + start += line_size; + } +} + +/* Write-back L1 and L2 cache entry */ +static inline void ax45mp_cpu_dcache_wb_range(unsigned long start, unsigned long end, + unsigned long line_size) +{ + ax45mp_cpu_cache_operation(start, end, line_size, + AX45MP_CCTL_L1D_VA_WB, + AX45MP_CCTL_L2_PA_WB); +} + +/* Invalidate the L1 and L2 cache entry */ +static inline void ax45mp_cpu_dcache_inval_range(unsigned long start, unsigned long end, + unsigned long line_size) +{ + ax45mp_cpu_cache_operation(start, end, line_size, + AX45MP_CCTL_L1D_VA_INVAL, + AX45MP_CCTL_L2_PA_INVAL); +} + +void ax45mp_dma_cache_inv(void *vaddr, unsigned long size) +{ + unsigned long start = (unsigned long)vaddr; + char cache_buf[2][AX45MP_CACHE_LINE_SIZE]; + unsigned long end = start + size; + unsigned long old_start = start; + unsigned long old_end = end; + unsigned long line_size; + unsigned long flags; + + if (unlikely(start == end)) + return; + + line_size = ax45mp_priv.ax45mp_cache_line_size; + + memset(&cache_buf, 0x0, sizeof(cache_buf)); + start = start & (~(line_size - 1)); + end = ((end + line_size - 1) & (~(line_size - 1))); + + local_irq_save(flags); + if (unlikely(start != old_start)) + memcpy(&cache_buf[0][0], (void *)start, line_size); + + if (unlikely(end != old_end)) + memcpy(&cache_buf[1][0], (void *)(old_end & (~(line_size - 1))), line_size); + + ax45mp_cpu_dcache_inval_range(start, end, line_size); + + if (unlikely(start != old_start)) + memcpy((void *)start, &cache_buf[0][0], (old_start & (line_size - 1))); + + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(ax45mp_dma_cache_inv); + +void ax45mp_dma_cache_wback(void *vaddr, unsigned long size) +{ + unsigned long start = (unsigned long)vaddr; + unsigned long end = start + size; + unsigned long line_size; + unsigned long flags; + + line_size = ax45mp_priv.ax45mp_cache_line_size; + start = start & (~(line_size - 1)); + local_irq_save(flags); + ax45mp_cpu_dcache_wb_range(start, end, line_size); + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(ax45mp_dma_cache_wback); + +void ax45mp_dma_cache_wback_inv(void *vaddr, unsigned long size) +{ + ax45mp_dma_cache_wback(vaddr, size); + ax45mp_dma_cache_inv(vaddr, size); +} +EXPORT_SYMBOL_GPL(ax45mp_dma_cache_wback_inv); + +static int ax45mp_get_l2_line_size(struct device_node *np) +{ + int ret; + + ret = of_property_read_u32(np, "cache-line-size", &ax45mp_priv.ax45mp_cache_line_size); + if (ret) { + pr_err("Failed to get cache-line-size, defaulting to 64 bytes\n"); + return ret; + } + + if (ax45mp_priv.ax45mp_cache_line_size != AX45MP_CACHE_LINE_SIZE) { + pr_err("Expected cache-line-size to be 64 bytes (found:%u)\n", + ax45mp_priv.ax45mp_cache_line_size); + return ret; + } + + return 0; +} + +static const struct of_device_id ax45mp_cache_ids[] = { + { .compatible = "andestech,ax45mp-cache" }, + { /* sentinel */ } +}; + +static int __init ax45mp_cache_init(void) +{ + struct device_node *np; + struct resource res; + int ret; + + np = of_find_matching_node(NULL, ax45mp_cache_ids); + if (!of_device_is_available(np)) + return -ENODEV; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + + /* + * If IOCP is present on the Andes AX45MP core riscv_cbom_block_size + * will be 0 for sure, so we can definitely rely on it. If + * riscv_cbom_block_size = 0 we don't need to handle CMO using SW any + * more so we just return success here and only if its being set we + * continue further in the probe path. + */ + if (!riscv_cbom_block_size) + return 0; + + ax45mp_priv.l2c_base = ioremap(res.start, resource_size(&res)); + if (!ax45mp_priv.l2c_base) + return -ENOMEM; + + ret = ax45mp_get_l2_line_size(np); + if (ret) { + iounmap(ax45mp_priv.l2c_base); + return ret; + } + + return 0; +} +early_initcall(ax45mp_cache_init); -- 2.25.1