lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu,  9 May 2024 09:43:56 +0800
From: Shengjiu Wang <shengjiu.wang@....com>
To: abelvesa@...nel.org,
	peng.fan@....com,
	mturquette@...libre.com,
	sboyd@...nel.org,
	robh@...nel.org,
	krzk+dt@...nel.org,
	conor+dt@...nel.org,
	shawnguo@...nel.org,
	s.hauer@...gutronix.de,
	kernel@...gutronix.de,
	festevam@...il.com,
	marex@...x.de,
	imx@...ts.linux.dev,
	shengjiu.wang@...il.com
Cc: linux-clk@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org,
	linux-kernel@...r.kernel.org,
	devicetree@...r.kernel.org
Subject: [PATCH v2 2/4] clk: imx: clk-audiomix: Add reset controller

Audiomix block control can be a reset controller for
Enhanced Audio Return Channel (EARC), which is one of
modules in this audiomix subsystem.

The EARC PHY software reset and EARC controller software
reset need to be supported.

Signed-off-by: Shengjiu Wang <shengjiu.wang@....com>
---
 drivers/clk/imx/clk-imx8mp-audiomix.c | 82 +++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c
index b381d6f784c8..e84365cef71b 100644
--- a/drivers/clk/imx/clk-imx8mp-audiomix.c
+++ b/drivers/clk/imx/clk-imx8mp-audiomix.c
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset-controller.h>
 
 #include <dt-bindings/clock/imx8mp-clock.h>
 
@@ -35,6 +36,8 @@
 #define SAI_PLL_MNIT_CTL	0x410
 #define IPG_LP_CTRL		0x504
 
+#define EARC_RESET_MASK		0x3
+
 #define SAIn_MCLK1_PARENT(n)						\
 static const struct clk_parent_data					\
 clk_imx8mp_audiomix_sai##n##_mclk1_parents[] = {			\
@@ -212,6 +215,7 @@ static const u16 audiomix_regs[] = {
 struct clk_imx8mp_audiomix_priv {
 	void __iomem *base;
 	u32 regs_save[ARRAY_SIZE(audiomix_regs)];
+	struct reset_controller_dev rcdev;
 
 	/* Must be last */
 	struct clk_hw_onecell_data clk_data;
@@ -232,6 +236,80 @@ static void clk_imx8mp_audiomix_save_restore(struct device *dev, bool save)
 	}
 }
 
+static int clk_imx8mp_audiomix_reset_set(struct reset_controller_dev *rcdev,
+					 unsigned long id, bool assert)
+{
+	struct clk_imx8mp_audiomix_priv *drvdata = container_of(rcdev,
+				struct clk_imx8mp_audiomix_priv, rcdev);
+	unsigned int mask = BIT(id);
+	u32 reg;
+
+	pm_runtime_get_sync(rcdev->dev);
+
+	/* bit = 0 reset, bit = 1 unreset */
+	reg = readl(drvdata->base + EARC);
+	if (assert)
+		writel(reg & ~mask, drvdata->base + EARC);
+	else
+		writel(reg | mask, drvdata->base + EARC);
+
+	pm_runtime_put_sync(rcdev->dev);
+
+	return 0;
+}
+
+static int clk_imx8mp_audiomix_reset_reset(struct reset_controller_dev *rcdev,
+					   unsigned long id)
+{
+	clk_imx8mp_audiomix_reset_set(rcdev, id, true);
+
+	return clk_imx8mp_audiomix_reset_set(rcdev, id, false);
+}
+
+static int clk_imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
+					    unsigned long id)
+{
+	return clk_imx8mp_audiomix_reset_set(rcdev, id, true);
+}
+
+static int clk_imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
+					      unsigned long id)
+{
+	return clk_imx8mp_audiomix_reset_set(rcdev, id, false);
+}
+
+static int clk_imx8mp_audiomix_reset_xlate(struct reset_controller_dev *rcdev,
+					   const struct of_phandle_args *reset_spec)
+{
+	unsigned long id = reset_spec->args[0];
+
+	if (!(BIT(id) & EARC_RESET_MASK))
+		return -EINVAL;
+
+	return id;
+}
+
+static const struct reset_control_ops clk_imx8mp_audiomix_reset_ops = {
+	.reset		= clk_imx8mp_audiomix_reset_reset,
+	.assert		= clk_imx8mp_audiomix_reset_assert,
+	.deassert	= clk_imx8mp_audiomix_reset_deassert,
+};
+
+static int clk_imx8mp_audiomix_register_reset_controller(struct device *dev)
+{
+	struct clk_imx8mp_audiomix_priv *drvdata = dev_get_drvdata(dev);
+
+	drvdata->rcdev.owner     = THIS_MODULE;
+	drvdata->rcdev.nr_resets = fls(EARC_RESET_MASK);
+	drvdata->rcdev.ops       = &clk_imx8mp_audiomix_reset_ops;
+	drvdata->rcdev.of_node   = dev->of_node;
+	drvdata->rcdev.dev	 = dev;
+	drvdata->rcdev.of_reset_n_cells = 1;
+	drvdata->rcdev.of_xlate  = clk_imx8mp_audiomix_reset_xlate;
+
+	return devm_reset_controller_register(dev, &drvdata->rcdev);
+}
+
 static int clk_imx8mp_audiomix_probe(struct platform_device *pdev)
 {
 	struct clk_imx8mp_audiomix_priv *priv;
@@ -337,6 +415,10 @@ static int clk_imx8mp_audiomix_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_clk_register;
 
+	ret = clk_imx8mp_audiomix_register_reset_controller(dev);
+	if (ret)
+		goto err_clk_register;
+
 	pm_runtime_put_sync(dev);
 	return 0;
 
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ