linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Baluta <daniel.baluta@oss.nxp.com>
To: broonie@kernel.org, pierre-louis.bossart@linux.intel.com,
	lgirdwood@gmail.com, robh+dt@kernel.org,
	ranjani.sridharan@linux.intel.com, kai.vehmanen@linux.intel.com
Cc: devicetree@vger.kernel.org, shawnguo@kernel.org,
	kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com,
	peter.ujfalusi@linux.intel.com, alsa-devel@alsa-project.org,
	linux-kernel@vger.kernel.org, s-anna@ti.com,
	Daniel Baluta <daniel.baluta@nxp.com>
Subject: [PATCH v2 1/2] ASoC: SOF: imx: Add code to manage DSP related clocks
Date: Fri,  3 Sep 2021 17:53:39 +0300	[thread overview]
Message-ID: <20210903145340.225511-2-daniel.baluta@oss.nxp.com> (raw)
In-Reply-To: <20210903145340.225511-1-daniel.baluta@oss.nxp.com>

From: Daniel Baluta <daniel.baluta@nxp.com>

There are two types of clocks:
	* DSP IP clocks
	* DAI clocks

This clocks are necessary in order to power up DSP and DAIs.

We choose to enable DAI clocks here because of the way i.MX8/i.MX8X
design handles resources (including clocks).

All clocks are managed by a separate core (named SCU) which communicates
with Linux managed ARM core via a well known API.

We parse and enable the clocks in probe function and disable them in
remove function.

Future patches will introduce Power Management support so that we
disable clocks while DSP is not used or system enters power save.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
 sound/soc/sof/imx/imx-common.c | 44 ++++++++++++++++++++++++++++++++++
 sound/soc/sof/imx/imx-common.h | 13 ++++++++++
 sound/soc/sof/imx/imx8.c       | 37 ++++++++++++++++++++++++++++
 sound/soc/sof/imx/imx8m.c      | 34 ++++++++++++++++++++++++++
 4 files changed, 128 insertions(+)

diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c
index 8826ef94f04a..f9d650ad3846 100644
--- a/sound/soc/sof/imx/imx-common.c
+++ b/sound/soc/sof/imx/imx-common.c
@@ -74,4 +74,48 @@ void imx8_dump(struct snd_sof_dev *sdev, u32 flags)
 }
 EXPORT_SYMBOL(imx8_dump);
 
+int imx8_parse_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks)
+{
+	int ret;
+
+	ret = devm_clk_bulk_get(sdev->dev, clks->num_dsp_clks, clks->dsp_clks);
+	if (ret) {
+		dev_err(sdev->dev, "Failed to request DSP clocks\n");
+		return ret;
+	}
+
+	ret = devm_clk_bulk_get_optional(sdev->dev, clks->num_dai_clks, clks->dai_clks);
+	if (ret) {
+		dev_err(sdev->dev, "Failed to request DAI clks\n");
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(imx8_parse_clocks);
+
+int imx8_enable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks)
+{
+	int ret;
+
+	ret = clk_bulk_prepare_enable(clks->num_dsp_clks, clks->dsp_clks);
+	if (ret)
+		return ret;
+	ret = clk_bulk_prepare_enable(clks->num_dai_clks, clks->dai_clks);
+	if (ret) {
+		clk_bulk_disable_unprepare(clks->num_dsp_clks, clks->dsp_clks);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(imx8_enable_clocks);
+
+void imx8_disable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks)
+{
+	clk_bulk_disable_unprepare(clks->num_dsp_clks, clks->dsp_clks);
+	clk_bulk_disable_unprepare(clks->num_dai_clks, clks->dai_clks);
+}
+EXPORT_SYMBOL(imx8_disable_clocks);
+
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/sof/imx/imx-common.h b/sound/soc/sof/imx/imx-common.h
index 1cc7d6704182..54fba9fcd861 100644
--- a/sound/soc/sof/imx/imx-common.h
+++ b/sound/soc/sof/imx/imx-common.h
@@ -3,6 +3,8 @@
 #ifndef __IMX_COMMON_H__
 #define __IMX_COMMON_H__
 
+#include <linux/clk.h>
+
 #define EXCEPT_MAX_HDR_SIZE	0x400
 #define IMX8_STACK_DUMP_SIZE 32
 
@@ -13,4 +15,15 @@ void imx8_get_registers(struct snd_sof_dev *sdev,
 
 void imx8_dump(struct snd_sof_dev *sdev, u32 flags);
 
+struct imx_clocks {
+	struct clk_bulk_data *dsp_clks;
+	int num_dsp_clks;
+	struct clk_bulk_data *dai_clks;
+	int num_dai_clks;
+};
+
+int imx8_parse_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks);
+int imx8_enable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks);
+void imx8_disable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks);
+
 #endif
diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c
index fc1720c211a3..5370d34edd61 100644
--- a/sound/soc/sof/imx/imx8.c
+++ b/sound/soc/sof/imx/imx8.c
@@ -41,6 +41,25 @@
 #define MBOX_OFFSET	0x800000
 #define MBOX_SIZE	0x1000
 
+/* DSP clocks */
+struct clk_bulk_data imx8_dsp_clks[] = {
+	{ .id = "ipg" },
+	{ .id = "ocram" },
+	{ .id = "core" },
+};
+
+/* DAI clocks */
+struct clk_bulk_data imx8_dai_clks[] = {
+	{ .id = "esai0_core" },
+	{ .id = "esai0_extal" },
+	{ .id = "esai0_spba" },
+	{ .id = "sai1_bus" },
+	{ .id = "sai1_mclk0" },
+	{ .id = "sai1_mclk1" },
+	{ .id = "sai1_mclk2" },
+	{ .id = "sai1_mclk3" },
+};
+
 struct imx8_priv {
 	struct device *dev;
 	struct snd_sof_dev *sdev;
@@ -57,6 +76,7 @@ struct imx8_priv {
 	struct device **pd_dev;
 	struct device_link **link;
 
+	struct imx_clocks *clks;
 };
 
 static void imx8_get_reply(struct snd_sof_dev *sdev)
@@ -223,6 +243,10 @@ static int imx8_probe(struct snd_sof_dev *sdev)
 	if (!priv)
 		return -ENOMEM;
 
+	priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL);
+	if (!priv->clks)
+		return -ENOMEM;
+
 	sdev->num_cores = 1;
 	sdev->pdata->hw_pdata = priv;
 	priv->dev = sdev->dev;
@@ -336,6 +360,18 @@ static int imx8_probe(struct snd_sof_dev *sdev)
 	/* set default mailbox offset for FW ready message */
 	sdev->dsp_box.offset = MBOX_OFFSET;
 
+	/* init clocks info */
+	priv->clks->dsp_clks = imx8_dsp_clks;
+	priv->clks->num_dsp_clks = ARRAY_SIZE(imx8_dsp_clks);
+	priv->clks->dai_clks = imx8_dai_clks;
+	priv->clks->num_dai_clks = ARRAY_SIZE(imx8_dai_clks);
+
+	ret = imx8_parse_clocks(sdev, priv->clks);
+	if (ret < 0)
+		goto exit_pdev_unregister;
+
+	imx8_enable_clocks(sdev, priv->clks);
+
 	return 0;
 
 exit_pdev_unregister:
@@ -354,6 +390,7 @@ static int imx8_remove(struct snd_sof_dev *sdev)
 	struct imx8_priv *priv = sdev->pdata->hw_pdata;
 	int i;
 
+	imx8_disable_clocks(sdev, priv->clks);
 	platform_device_unregister(priv->ipc_dev);
 
 	for (i = 0; i < priv->num_domains; i++) {
diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c
index 30624fafc632..fea1b72bebaa 100644
--- a/sound/soc/sof/imx/imx8m.c
+++ b/sound/soc/sof/imx/imx8m.c
@@ -23,6 +23,21 @@
 #define MBOX_OFFSET	0x800000
 #define MBOX_SIZE	0x1000
 
+struct clk_bulk_data imx8m_dsp_clks[] = {
+	{ .id = "ipg" },
+	{ .id = "ocram" },
+	{ .id = "core" },
+};
+
+struct clk_bulk_data imx8m_dai_clks[] = {
+	{ .id = "sai3_bus" },
+	{ .id = "sai3_mclk0" },
+	{ .id = "sai3_mclk1" },
+	{ .id = "sai3_mclk2" },
+	{ .id = "sai3_mclk3" },
+	{ .id = "sdma3_root" },
+};
+
 struct imx8m_priv {
 	struct device *dev;
 	struct snd_sof_dev *sdev;
@@ -30,6 +45,8 @@ struct imx8m_priv {
 	/* DSP IPC handler */
 	struct imx_dsp_ipc *dsp_ipc;
 	struct platform_device *ipc_dev;
+
+	struct imx_clocks *clks;
 };
 
 static void imx8m_get_reply(struct snd_sof_dev *sdev)
@@ -143,6 +160,10 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
 	if (!priv)
 		return -ENOMEM;
 
+	priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL);
+	if (!priv->clks)
+		return -ENOMEM;
+
 	sdev->num_cores = 1;
 	sdev->pdata->hw_pdata = priv;
 	priv->dev = sdev->dev;
@@ -211,6 +232,18 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
 	/* set default mailbox offset for FW ready message */
 	sdev->dsp_box.offset = MBOX_OFFSET;
 
+	/* init clocks info */
+	priv->clks->dsp_clks = imx8m_dsp_clks;
+	priv->clks->num_dsp_clks = ARRAY_SIZE(imx8m_dsp_clks);
+	priv->clks->dai_clks = imx8m_dai_clks;
+	priv->clks->num_dai_clks = ARRAY_SIZE(imx8m_dai_clks);
+
+	ret = imx8_parse_clocks(sdev, priv->clks);
+	if (ret < 0)
+		goto exit_pdev_unregister;
+
+	imx8_enable_clocks(sdev, priv->clks);
+
 	return 0;
 
 exit_pdev_unregister:
@@ -222,6 +255,7 @@ static int imx8m_remove(struct snd_sof_dev *sdev)
 {
 	struct imx8m_priv *priv = sdev->pdata->hw_pdata;
 
+	imx8_disable_clocks(sdev, priv->clks);
 	platform_device_unregister(priv->ipc_dev);
 
 	return 0;
-- 
2.27.0


  reply	other threads:[~2021-09-03 14:54 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-03 14:53 [PATCH v2 0/2] " Daniel Baluta
2021-09-03 14:53 ` Daniel Baluta [this message]
2021-09-03 16:06   ` [PATCH v2 1/2] ASoC: SOF: imx: " Pierre-Louis Bossart
2021-09-03 14:53 ` [PATCH v2 2/2] dt-bindings: dsp: fsl: Add DSP optional clocks documentation Daniel Baluta
2021-09-03 16:53   ` Rob Herring
2021-09-04 14:50     ` Daniel Baluta
2021-09-07 13:09       ` Rob Herring
2021-09-09 11:20         ` Daniel Baluta
2021-09-09 17:15           ` Rob Herring

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=20210903145340.225511-2-daniel.baluta@oss.nxp.com \
    --to=daniel.baluta@oss.nxp.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=daniel.baluta@nxp.com \
    --cc=devicetree@vger.kernel.org \
    --cc=festevam@gmail.com \
    --cc=kai.vehmanen@linux.intel.com \
    --cc=kernel@pengutronix.de \
    --cc=lgirdwood@gmail.com \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peter.ujfalusi@linux.intel.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=ranjani.sridharan@linux.intel.com \
    --cc=robh+dt@kernel.org \
    --cc=s-anna@ti.com \
    --cc=shawnguo@kernel.org \
    --subject='Re: [PATCH v2 1/2] ASoC: SOF: imx: Add code to manage DSP related clocks' \
    /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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).