Received: by 2002:a05:6358:489b:b0:bb:da1:e618 with SMTP id x27csp3529042rwn; Sat, 10 Sep 2022 13:52:51 -0700 (PDT) X-Google-Smtp-Source: AA6agR7dSJIMIl1mPQFipyl5BCAF3NmirnXXC4V/Bf3+zUOdognSP4jmC2ZmYgPyQWWixQI4LAjV X-Received: by 2002:a17:902:f651:b0:174:3c03:6be3 with SMTP id m17-20020a170902f65100b001743c036be3mr19217685plg.113.1662843171358; Sat, 10 Sep 2022 13:52:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662843171; cv=none; d=google.com; s=arc-20160816; b=DeOyShTi9fCNvoyIEadfYgQkkUEn8LxVThcdUvS7tC96LoZrJmxSssvcO0cY9BdL0o KPLH1ydI9fuXEg9uGnbITXYuGqhOf4R8PzSrQR0TOJMaoUDKjL0sA3Dv/lAd4Gnm1AOi GkpqncHNTE0Y4pvhNtPgNGjM/5bLUwV7maW3V5HQA8/3GSU1oUs3cNgV11i8aoW6X5Ro 0d9FdiDstwoCSfkh3rTPBxzNheH7cVWMI6IrE4pwIoNtJQWBIlwOc4eNwcFF3Y/K7rIx dbh+5rHgXhSFknvMc3628zrGKBfUusbBfstZCrBOQ2cwb/GRRUOm/078diC+Y9z8VGgf DdBQ== 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:dkim-filter; bh=T3CV91djzYazoRWrEPNnzkdz0BKd0JHDUI0FBn6UuwM=; b=cHCY/2oG5FESZxwQRb2KrhsSOW2QEstFLgRz46VZJ0r3MmoSUpLJZ/ljMfWpgfpS4B I3uf43a2xhvDqWAH3DLPPvsQxQ+fxWh+m2UY5kYap4cAryvbVW51D/L4vHuyeA4wHz8l Ek2u1KI35OkEc+fGU25isg4szN+6Zs1Rx45A9BrvSmw4Hs9NSzDgVmBrD5btP3BpFGYk oJfsMOrm16UEp6C6R7WsgtV2TIfGGsMyJrHqpVeLivtCS4Qpc96Tl2jDp+/OaoVTvkCI hS0VkVJwsMmrAonoB9tB1mSXmE4YDKSXhcEtGGQRtltzSZcoTk2rO+uhkKr8p7jJCbPH 29wg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baikalelectronics.ru header.s=mail header.b=qibWuN65; 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=REJECT sp=REJECT dis=NONE) header.from=baikalelectronics.ru Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id oa15-20020a17090b1bcf00b0020297249987si4724205pjb.124.2022.09.10.13.52.40; Sat, 10 Sep 2022 13:52:51 -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=@baikalelectronics.ru header.s=mail header.b=qibWuN65; 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=REJECT sp=REJECT dis=NONE) header.from=baikalelectronics.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229905AbiIJT6V (ORCPT + 99 others); Sat, 10 Sep 2022 15:58:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229831AbiIJT5a (ORCPT ); Sat, 10 Sep 2022 15:57:30 -0400 Received: from mail.baikalelectronics.com (mail.baikalelectronics.com [87.245.175.230]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2738C476ED; Sat, 10 Sep 2022 12:57:25 -0700 (PDT) Received: from mail (mail.baikal.int [192.168.51.25]) by mail.baikalelectronics.com (Postfix) with ESMTP id D985ADBF; Sat, 10 Sep 2022 23:00:59 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.baikalelectronics.com D985ADBF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baikalelectronics.ru; s=mail; t=1662840059; bh=T3CV91djzYazoRWrEPNnzkdz0BKd0JHDUI0FBn6UuwM=; h=From:To:CC:Subject:Date:In-Reply-To:References:From; b=qibWuN65MgBVxy1h7ZUQ9ssH9U/dk6eHcoTepjtiDassDrvkIxRcsRWMeUc1kBycJ gUYk+B1TQpUrfMIqzyXcDi4mEAgfp9bxJzKwvGIk+01YX/SNlTau+ywxOOihi0P/jF ZXYOTNS7vsNvLTvXOlVDlCu6zc8QeoVgm+Ifpt/c= Received: from localhost (192.168.168.10) by mail (192.168.51.25) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Sat, 10 Sep 2022 22:57:09 +0300 From: Serge Semin To: Rob Herring , Krzysztof Kozlowski , Michal Simek , Borislav Petkov , Mauro Carvalho Chehab , Tony Luck , James Morse , Robert Richter CC: Serge Semin , Serge Semin , Alexey Malahov , Michail Ivanov , Pavel Parkhomenko , Punnaiah Choudary Kalluri , Manish Narani , Dinh Nguyen , Rob Herring , Krzysztof Kozlowski , , , , Subject: [PATCH v2 12/15] EDAC/synopsys: Add reference clocks support Date: Sat, 10 Sep 2022 22:56:56 +0300 Message-ID: <20220910195659.11843-13-Sergey.Semin@baikalelectronics.ru> In-Reply-To: <20220910195659.11843-1-Sergey.Semin@baikalelectronics.ru> References: <20220910195659.11843-1-Sergey.Semin@baikalelectronics.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: MAIL.baikal.int (192.168.51.25) To mail (192.168.51.25) X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE 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 Currently the driver doesn't support any clock-related resources request and handling, fairly assuming that all of them are supposed to be enabled anyway in order for the system to work correctly. It's true for the Core and AXI Ports reference clocks, but the CSR (APB) and Scrubber clocks might still be disabled in case if the system firmware doesn't imply any other software touching the DDR controller internals. Since the DW uMCTL2 DDRC driver does access the controller registers at the very least we need to make sure the APB clock is enabled. Let's add the reference clocks support then. First of all the driver will request all the clocks possibly defined for the controller (Core, AXI, APB and Scrubber). Secondly the APB clock will be enabled/disabled only since the Scrubber is currently unsupported by the driver, and the Core and AXI clocks feed the critical system parts so we need to avoid touching them with a risk to de-stabilize the system memory. Please note the clocks connection IDs have been chosen in accordance with the DT-bindings. Signed-off-by: Serge Semin --- drivers/edac/synopsys_edac.c | 101 +++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 8d8952826bce..4b204b2050d4 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -301,6 +302,25 @@ enum snps_ecc_mode { SNPS_ECC_ADVX4X8 = 5, }; +/** + * enum snps_ref_clk - DW uMCTL2 DDR controller clocks. + * @SNPS_CSR_CLK: CSR/APB interface clock. + * @SNPS_AXI_CLK: AXI (AHB) Port reference clock. + * @SNPS_CORE_CLK: DDR controller (including DFI) clock. SDRAM clock + * matches runs with this freq in 1:1 ratio mode and + * with twice of this freq in case of 1:2 ratio mode. + * @SNPS_SBR_CLK: Scrubber port reference clock (synchronous to + * the core clock). + * @SNPS_MAX_NCLK: Total number of clocks. + */ +enum snps_ref_clk { + SNPS_CSR_CLK, + SNPS_AXI_CLK, + SNPS_CORE_CLK, + SNPS_SBR_CLK, + SNPS_MAX_NCLK +}; + /** * struct snps_ddrc_info - DDR controller platform parameters. * @caps: DDR controller capabilities. @@ -405,6 +425,7 @@ struct snps_ecc_error_info { * @pdev: Platform device. * @baseaddr: Base address of the DDR controller. * @lock: Concurrent CSRs access lock. + * @clks: Controller reference clocks. * @message: Buffer for framing the event specific info. */ struct snps_edac_priv { @@ -414,6 +435,7 @@ struct snps_edac_priv { struct platform_device *pdev; void __iomem *baseaddr; spinlock_t lock; + struct clk_bulk_data clks[SNPS_MAX_NCLK]; char message[SNPS_EDAC_MSG_SIZE]; }; @@ -974,6 +996,60 @@ static struct snps_edac_priv *snps_create_data(struct platform_device *pdev) return priv; } +/** + * snps_get_res - Get platform device resources. + * @priv: DDR memory controller private instance data. + * + * It's supposed to request all the controller resources available for the + * particular platform and enable all the required for the driver normal + * work. Note only the CSR and Scrubber clocks are supposed to be switched + * on/off by the driver. + * + * Return: negative errno if failed to get the resources, otherwise - zero. + */ +static int snps_get_res(struct snps_edac_priv *priv) +{ + const char * const ids[] = { + [SNPS_CSR_CLK] = "pclk", + [SNPS_AXI_CLK] = "aclk", + [SNPS_CORE_CLK] = "core", + [SNPS_SBR_CLK] = "sbr", + }; + int i, rc; + + for (i = 0; i < SNPS_MAX_NCLK; i++) + priv->clks[i].id = ids[i]; + + rc = devm_clk_bulk_get_optional(&priv->pdev->dev, SNPS_MAX_NCLK, + priv->clks); + if (rc) { + edac_printk(KERN_INFO, EDAC_MC, "Failed to get ref clocks\n"); + return rc; + } + + /* + * Don't touch the Core and AXI clocks since they are critical for the + * stable system functioning and are supposed to have been enabled + * anyway. + */ + rc = clk_prepare_enable(priv->clks[SNPS_CSR_CLK].clk); + if (rc) { + edac_printk(KERN_INFO, EDAC_MC, "Couldn't enable CSR clock\n"); + return rc; + } + + return 0; +} + +/** + * snps_put_res - Put platform device resources. + * @priv: DDR memory controller private instance data. + */ +static void snps_put_res(struct snps_edac_priv *priv) +{ + clk_disable_unprepare(priv->clks[SNPS_CSR_CLK].clk); +} + /* * zynqmp_init_plat - ZynqMP-specific platform initialization. * @priv: DDR memory controller private data. @@ -1707,9 +1783,17 @@ static int snps_ddrc_info_show(struct seq_file *s, void *data) { struct mem_ctl_info *mci = s->private; struct snps_edac_priv *priv = mci->pvt_info; + unsigned long rate; seq_printf(s, "SDRAM: %s\n", edac_mem_types[priv->info.sdram_mode]); + rate = clk_get_rate(priv->clks[SNPS_CORE_CLK].clk); + if (rate) { + rate = rate / HZ_PER_MHZ; + seq_printf(s, "Clock: Core %luMHz SDRAM %luMHz\n", + rate, priv->info.freq_ratio * rate); + } + seq_printf(s, "DQ bus: %u/%s\n", (BITS_PER_BYTE << priv->info.dq_width), priv->info.dq_mode == SNPS_DQ_FULL ? "Full" : priv->info.dq_mode == SNPS_DQ_HALF ? "Half" : @@ -2018,15 +2102,21 @@ static int snps_mc_probe(struct platform_device *pdev) if (IS_ERR(priv)) return PTR_ERR(priv); - rc = snps_get_ddrc_info(priv); + rc = snps_get_res(priv); if (rc) return rc; + rc = snps_get_ddrc_info(priv); + if (rc) + goto put_res; + snps_get_addr_map(priv); mci = snps_mc_create(priv); - if (IS_ERR(mci)) - return PTR_ERR(mci); + if (IS_ERR(mci)) { + rc = PTR_ERR(mci); + goto put_res; + } rc = snps_setup_irq(mci); if (rc) @@ -2046,6 +2136,9 @@ static int snps_mc_probe(struct platform_device *pdev) free_edac_mc: snps_mc_free(mci); +put_res: + snps_put_res(priv); + return rc; } @@ -2066,6 +2159,8 @@ static int snps_mc_remove(struct platform_device *pdev) snps_mc_free(mci); + snps_put_res(priv); + return 0; } -- 2.37.2