All of lore.kernel.org
 help / color / mirror / Atom feed
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
To: Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Michal Simek <michal.simek@xilinx.com>,
	Borislav Petkov <bp@alien8.de>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Tony Luck <tony.luck@intel.com>,
	James Morse <james.morse@arm.com>,
	Robert Richter <rric@kernel.org>
Cc: Serge Semin <Sergey.Semin@baikalelectronics.ru>,
	Serge Semin <fancer.lancer@gmail.com>,
	Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>,
	Michail Ivanov <Michail.Ivanov@baikalelectronics.ru>,
	Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>,
	Punnaiah Choudary Kalluri <punnaiah.choudary.kalluri@xilinx.com>,
	Manish Narani <manish.narani@xilinx.com>,
	Dinh Nguyen <dinguyen@kernel.org>, Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>,
	<devicetree@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-edac@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: [PATCH v3 10/13] EDAC/synopsys: Add reference clocks support
Date: Fri, 30 Sep 2022 02:41:18 +0300	[thread overview]
Message-ID: <20220929234121.13955-11-Sergey.Semin@baikalelectronics.ru> (raw)
In-Reply-To: <20220929234121.13955-1-Sergey.Semin@baikalelectronics.ru>

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 <Sergey.Semin@baikalelectronics.ru>
---
 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 <linux/bitfield.h>
 #include <linux/bits.h>
+#include <linux/clk.h>
 #include <linux/edac.h>
 #include <linux/fs.h>
 #include <linux/log2.h>
@@ -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.3



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
To: Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Michal Simek <michal.simek@xilinx.com>,
	Borislav Petkov <bp@alien8.de>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Tony Luck <tony.luck@intel.com>,
	James Morse <james.morse@arm.com>,
	Robert Richter <rric@kernel.org>
Cc: Serge Semin <Sergey.Semin@baikalelectronics.ru>,
	Serge Semin <fancer.lancer@gmail.com>,
	Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>,
	Michail Ivanov <Michail.Ivanov@baikalelectronics.ru>,
	Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>,
	Punnaiah Choudary Kalluri  <punnaiah.choudary.kalluri@xilinx.com>,
	Manish Narani <manish.narani@xilinx.com>,
	Dinh Nguyen <dinguyen@kernel.org>, Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>,
	<devicetree@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-edac@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: [PATCH v3 10/13] EDAC/synopsys: Add reference clocks support
Date: Fri, 30 Sep 2022 02:41:18 +0300	[thread overview]
Message-ID: <20220929234121.13955-11-Sergey.Semin@baikalelectronics.ru> (raw)
In-Reply-To: <20220929234121.13955-1-Sergey.Semin@baikalelectronics.ru>

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 <Sergey.Semin@baikalelectronics.ru>
---
 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 <linux/bitfield.h>
 #include <linux/bits.h>
+#include <linux/clk.h>
 #include <linux/edac.h>
 #include <linux/fs.h>
 #include <linux/log2.h>
@@ -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.3



  parent reply	other threads:[~2022-09-30  0:06 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-29 23:41 [PATCH v3 00/13] EDAC/synopsys: Add generic resources and Baikal-T1 support Serge Semin
2022-09-29 23:41 ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 01/13] dt-bindings: memory: snps: Convert the schema to being generic Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-10-05 13:12   ` Rob Herring
2022-10-05 13:12     ` Rob Herring
2022-09-29 23:41 ` [PATCH v3 02/13] dt-bindings: memory: Add Baikal-T1 DDRC DT-schema Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-10-03 13:24   ` Rob Herring
2022-10-03 13:24     ` Rob Herring
2022-10-05 14:59     ` Krzysztof Kozlowski
2022-10-05 14:59       ` Krzysztof Kozlowski
2022-10-06 12:26       ` Serge Semin
2022-10-06 12:26         ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 03/13] EDAC/synopsys: Add multi-ranked memory support Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 04/13] EDAC/synopsys: Add optional ECC Scrub support Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 05/13] EDAC/synopsys: Drop ECC poison address from private data Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 06/13] EDAC/synopsys: Add data poisoning disable support Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 07/13] EDAC/synopsys: Split up ECC UE/CE IRQs handler Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 08/13] EDAC/synopsys: Add individual named ECC IRQs support Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 09/13] EDAC/synopsys: Add DFI alert_n IRQ support Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` Serge Semin [this message]
2022-09-29 23:41   ` [PATCH v3 10/13] EDAC/synopsys: Add reference clocks support Serge Semin
2022-09-29 23:41 ` [PATCH v3 11/13] EDAC/synopsys: Add ECC Scrubber support Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 12/13] EDAC/synopsys: Drop vendor-specific arch dependency Serge Semin
2022-09-29 23:41   ` Serge Semin
2022-09-29 23:41 ` [PATCH v3 13/13] EDAC/synopsys: Add Baikal-T1 DDRC support Serge Semin
2022-09-29 23:41   ` Serge Semin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220929234121.13955-11-Sergey.Semin@baikalelectronics.ru \
    --to=sergey.semin@baikalelectronics.ru \
    --cc=Alexey.Malahov@baikalelectronics.ru \
    --cc=Michail.Ivanov@baikalelectronics.ru \
    --cc=Pavel.Parkhomenko@baikalelectronics.ru \
    --cc=bp@alien8.de \
    --cc=devicetree@vger.kernel.org \
    --cc=dinguyen@kernel.org \
    --cc=fancer.lancer@gmail.com \
    --cc=james.morse@arm.com \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=krzysztof.kozlowski@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-edac@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=manish.narani@xilinx.com \
    --cc=mchehab@kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=punnaiah.choudary.kalluri@xilinx.com \
    --cc=robh+dt@kernel.org \
    --cc=robh@kernel.org \
    --cc=rric@kernel.org \
    --cc=tony.luck@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.