Commit 8253aa47 authored by Daniel Baluta's avatar Daniel Baluta Committed by Mark Brown

ASoC: SOF: imx: Add code to manage DSP related clocks

We need at least 3 clocks in order to power up and access
DSP core registers found on i.MX8QM, i.MX8QXP and i.MX8MP
platforms.

Add code to request these clocks and enable them at probe. Next
patches will add PM support which will only activate clocks when
DSP is used.

DSP clocks are already documented in
Documentation/devicetree/bindings/dsp/fsl,dsp.yaml

We choose to add:
	* imx8_parse_clocks
	* imx8_enable_clocks
	* imx8_disable_clocks

wrappers because in the future DSP will need to take care about the
clocks of other related Audio IPs (e.g SAI, ESAI).
Signed-off-by: default avatarDaniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: default avatarPaul Olaru <paul.olaru@oss.nxp.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20211119094319.81674-2-daniel.baluta@oss.nxp.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 626a3dfb
...@@ -74,4 +74,28 @@ void imx8_dump(struct snd_sof_dev *sdev, u32 flags) ...@@ -74,4 +74,28 @@ void imx8_dump(struct snd_sof_dev *sdev, u32 flags)
} }
EXPORT_SYMBOL(imx8_dump); 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;
}
EXPORT_SYMBOL(imx8_parse_clocks);
int imx8_enable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks)
{
return clk_bulk_prepare_enable(clks->num_dsp_clks, clks->dsp_clks);
}
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);
}
EXPORT_SYMBOL(imx8_disable_clocks);
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#ifndef __IMX_COMMON_H__ #ifndef __IMX_COMMON_H__
#define __IMX_COMMON_H__ #define __IMX_COMMON_H__
#include <linux/clk.h>
#define EXCEPT_MAX_HDR_SIZE 0x400 #define EXCEPT_MAX_HDR_SIZE 0x400
#define IMX8_STACK_DUMP_SIZE 32 #define IMX8_STACK_DUMP_SIZE 32
...@@ -13,4 +15,13 @@ void imx8_get_registers(struct snd_sof_dev *sdev, ...@@ -13,4 +15,13 @@ void imx8_get_registers(struct snd_sof_dev *sdev,
void imx8_dump(struct snd_sof_dev *sdev, u32 flags); void imx8_dump(struct snd_sof_dev *sdev, u32 flags);
struct imx_clocks {
struct clk_bulk_data *dsp_clks;
int num_dsp_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 #endif
...@@ -41,6 +41,13 @@ ...@@ -41,6 +41,13 @@
#define MBOX_OFFSET 0x800000 #define MBOX_OFFSET 0x800000
#define MBOX_SIZE 0x1000 #define MBOX_SIZE 0x1000
/* DSP clocks */
static struct clk_bulk_data imx8_dsp_clks[] = {
{ .id = "ipg" },
{ .id = "ocram" },
{ .id = "core" },
};
struct imx8_priv { struct imx8_priv {
struct device *dev; struct device *dev;
struct snd_sof_dev *sdev; struct snd_sof_dev *sdev;
...@@ -57,6 +64,7 @@ struct imx8_priv { ...@@ -57,6 +64,7 @@ struct imx8_priv {
struct device **pd_dev; struct device **pd_dev;
struct device_link **link; struct device_link **link;
struct imx_clocks *clks;
}; };
static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev) static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev)
...@@ -188,6 +196,10 @@ static int imx8_probe(struct snd_sof_dev *sdev) ...@@ -188,6 +196,10 @@ static int imx8_probe(struct snd_sof_dev *sdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL);
if (!priv->clks)
return -ENOMEM;
sdev->pdata->hw_pdata = priv; sdev->pdata->hw_pdata = priv;
priv->dev = sdev->dev; priv->dev = sdev->dev;
priv->sdev = sdev; priv->sdev = sdev;
...@@ -300,6 +312,16 @@ static int imx8_probe(struct snd_sof_dev *sdev) ...@@ -300,6 +312,16 @@ static int imx8_probe(struct snd_sof_dev *sdev)
/* set default mailbox offset for FW ready message */ /* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET; 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);
ret = imx8_parse_clocks(sdev, priv->clks);
if (ret < 0)
goto exit_pdev_unregister;
imx8_enable_clocks(sdev, priv->clks);
return 0; return 0;
exit_pdev_unregister: exit_pdev_unregister:
...@@ -318,6 +340,7 @@ static int imx8_remove(struct snd_sof_dev *sdev) ...@@ -318,6 +340,7 @@ static int imx8_remove(struct snd_sof_dev *sdev)
struct imx8_priv *priv = sdev->pdata->hw_pdata; struct imx8_priv *priv = sdev->pdata->hw_pdata;
int i; int i;
imx8_disable_clocks(sdev, priv->clks);
platform_device_unregister(priv->ipc_dev); platform_device_unregister(priv->ipc_dev);
for (i = 0; i < priv->num_domains; i++) { for (i = 0; i < priv->num_domains; i++) {
......
...@@ -23,6 +23,12 @@ ...@@ -23,6 +23,12 @@
#define MBOX_OFFSET 0x800000 #define MBOX_OFFSET 0x800000
#define MBOX_SIZE 0x1000 #define MBOX_SIZE 0x1000
static struct clk_bulk_data imx8m_dsp_clks[] = {
{ .id = "ipg" },
{ .id = "ocram" },
{ .id = "core" },
};
struct imx8m_priv { struct imx8m_priv {
struct device *dev; struct device *dev;
struct snd_sof_dev *sdev; struct snd_sof_dev *sdev;
...@@ -30,6 +36,8 @@ struct imx8m_priv { ...@@ -30,6 +36,8 @@ struct imx8m_priv {
/* DSP IPC handler */ /* DSP IPC handler */
struct imx_dsp_ipc *dsp_ipc; struct imx_dsp_ipc *dsp_ipc;
struct platform_device *ipc_dev; struct platform_device *ipc_dev;
struct imx_clocks *clks;
}; };
static int imx8m_get_mailbox_offset(struct snd_sof_dev *sdev) static int imx8m_get_mailbox_offset(struct snd_sof_dev *sdev)
...@@ -108,6 +116,10 @@ static int imx8m_probe(struct snd_sof_dev *sdev) ...@@ -108,6 +116,10 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL);
if (!priv->clks)
return -ENOMEM;
sdev->pdata->hw_pdata = priv; sdev->pdata->hw_pdata = priv;
priv->dev = sdev->dev; priv->dev = sdev->dev;
priv->sdev = sdev; priv->sdev = sdev;
...@@ -175,6 +187,16 @@ static int imx8m_probe(struct snd_sof_dev *sdev) ...@@ -175,6 +187,16 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
/* set default mailbox offset for FW ready message */ /* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET; 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);
ret = imx8_parse_clocks(sdev, priv->clks);
if (ret < 0)
goto exit_pdev_unregister;
imx8_enable_clocks(sdev, priv->clks);
return 0; return 0;
exit_pdev_unregister: exit_pdev_unregister:
...@@ -186,6 +208,7 @@ static int imx8m_remove(struct snd_sof_dev *sdev) ...@@ -186,6 +208,7 @@ static int imx8m_remove(struct snd_sof_dev *sdev)
{ {
struct imx8m_priv *priv = sdev->pdata->hw_pdata; struct imx8m_priv *priv = sdev->pdata->hw_pdata;
imx8_disable_clocks(sdev, priv->clks);
platform_device_unregister(priv->ipc_dev); platform_device_unregister(priv->ipc_dev);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment