linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Add support for DSP IPC protocol driver
@ 2019-06-27  8:12 Daniel Baluta
  2019-06-27  8:12 ` [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface Daniel Baluta
  2019-06-27  8:12 ` [PATCH v2 2/2] dt-bindings: dsp: fsl: Add DSP IPC binding support Daniel Baluta
  0 siblings, 2 replies; 6+ messages in thread
From: Daniel Baluta @ 2019-06-27  8:12 UTC (permalink / raw)
  To: shawnguo, robh+dt, o.rempel
  Cc: s.hauer, S.j. Wang, festevam, dl-linux-imx, Aisheng Dong,
	Anson Huang, linux-kernel, linux-arm-kernel, mark.rutland,
	devicetree, Daniel Baluta

Hifi4 DSP can be found on some i.MX8 platforms (e.g i.MX8QXP, i.MX8QM).
This patch series introduces the layer that allows Host CPU to
communicate with DSP.

This layer provides a doorbell and clients can used that to notify DSP
that a message is placed somewhere in the shared memory.

The protocol used is request - reply. Usually, Host/DSP write a message
in a shared memory area and notify the other side. The other side will
also write a reply in a designated shared memory area and then ring
the doorbell to let the counterpart that a message is ready.

Changes since v1: (after Rob's and Oleksij comments)
	- removed imx_dsp_get_handle now drivers wanting to use DSP IPC
          will get a reference to dsp_ipc node in dts.
        - added chip name in compatible string fsl,imx8qxp-dsp
	- avoid memory leaks
	- make dt_binding_check works fine now!

Daniel Baluta (2):
  firmware: imx: Add DSP IPC protocol interface
  dt-bindings: dsp: fsl: Add DSP IPC binding support

 .../devicetree/bindings/dsp/fsl,dsp_ipc.yaml  |  44 ++++++
 drivers/firmware/imx/Kconfig                  |  11 ++
 drivers/firmware/imx/Makefile                 |   1 +
 drivers/firmware/imx/imx-dsp.c                | 142 ++++++++++++++++++
 include/linux/firmware/imx/dsp.h              |  67 +++++++++
 5 files changed, 265 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dsp/fsl,dsp_ipc.yaml
 create mode 100644 drivers/firmware/imx/imx-dsp.c
 create mode 100644 include/linux/firmware/imx/dsp.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface
  2019-06-27  8:12 [PATCH v2 0/2] Add support for DSP IPC protocol driver Daniel Baluta
@ 2019-06-27  8:12 ` Daniel Baluta
  2019-07-09  5:48   ` Daniel Baluta
  2019-06-27  8:12 ` [PATCH v2 2/2] dt-bindings: dsp: fsl: Add DSP IPC binding support Daniel Baluta
  1 sibling, 1 reply; 6+ messages in thread
From: Daniel Baluta @ 2019-06-27  8:12 UTC (permalink / raw)
  To: shawnguo, robh+dt, o.rempel
  Cc: s.hauer, S.j. Wang, festevam, dl-linux-imx, Aisheng Dong,
	Anson Huang, linux-kernel, linux-arm-kernel, mark.rutland,
	devicetree, Daniel Baluta

Some of i.MX8 processors (e.g i.MX8QM, i.MX8QXP) contain
the Tensilica HiFi4 DSP for advanced pre- and post-audio
processing.

The communication between Host CPU and DSP firmware is
taking place using a shared memory area for message passing
and a dedicated Messaging Unit for notifications.

DSP IPC protocol driver offers a doorbell interface using
imx-mailbox API.

We use 4 MU channels (2 x TXDB, 2 x RXDB) to implement a
request-reply protocol.

Connection 0 (txdb0, rxdb0):
        - Host writes messasge to shared memory [SHMEM]
	- Host sends a request [MU]
	- DSP handles request [SHMEM]
	- DSP sends reply [MU]

Connection 1 (txdb1, rxdb1):
	- DSP writes a message to shared memory [SHMEM]
	- DSP sends a request [MU]
	- Host handles request [SHMEM]
	- Host sends reply [MU]

The protocol driver will be used by a Host client to
communicate with the DSP. First client will be the i.MX8
part from Sound Open Firmware infrastructure.

The protocol drivers offers the following interface:

On Tx:
   - imx_dsp_ring_doorbell, will be called to notify the DSP
   that it needs to handle a request.

On Rx:
   - clients need to provide two callbacks:
	.handle_reply
	.handle_request
  - the callbacks will be used by the protocol driver on
    notification arrival from DSP.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
 drivers/firmware/imx/Kconfig     |  11 +++
 drivers/firmware/imx/Makefile    |   1 +
 drivers/firmware/imx/imx-dsp.c   | 142 +++++++++++++++++++++++++++++++
 include/linux/firmware/imx/dsp.h |  67 +++++++++++++++
 4 files changed, 221 insertions(+)
 create mode 100644 drivers/firmware/imx/imx-dsp.c
 create mode 100644 include/linux/firmware/imx/dsp.h

diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index 42b566f8903f..ddb241708c31 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -1,4 +1,15 @@
 # SPDX-License-Identifier: GPL-2.0-only
+config IMX_DSP
+	bool "IMX DSP Protocol driver"
+	depends on IMX_MBOX
+	help
+	  This enables DSP IPC protocol between host CPU (Linux)
+	  and the firmware running on DSP.
+	  DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP).
+
+	  It acts like a doorbell. Client might use shared memory to
+	  exchange information with DSP side.
+
 config IMX_SCU
 	bool "IMX SCU Protocol driver"
 	depends on IMX_MBOX
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 802c4ad8e8f9..08bc9ddfbdfb 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_IMX_DSP)		+= imx-dsp.o
 obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o
 obj-$(CONFIG_IMX_SCU_PD)	+= scu-pd.o
diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
new file mode 100644
index 000000000000..c4d34a2fbff3
--- /dev/null
+++ b/drivers/firmware/imx/imx-dsp.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ *  Author: Daniel Baluta <daniel.baluta@nxp.com>
+ *
+ * Implementation of the DSP IPC interface (host side)
+ */
+
+#include <linux/firmware/imx/dsp.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/*
+ * imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP)
+ *
+ * @dsp: DSP IPC handle
+ * @chan_idx: index of the channel where to trigger the interrupt
+ *
+ * Returns non-negative value for success, negative value for error
+ */
+int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx)
+{
+	int ret;
+	struct imx_dsp_chan *dsp_chan;
+
+	if (idx >= DSP_MU_CHAN_NUM)
+		return -EINVAL;
+
+	dsp_chan = &ipc->chans[idx];
+	ret = mbox_send_message(dsp_chan->ch, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(imx_dsp_ring_doorbell);
+
+/*
+ * imx_dsp_handle_rx - rx callback used by imx mailbox
+ *
+ * @c: mbox client
+ * @msg: message received
+ *
+ * Users of DSP IPC will need to privde handle_reply and handle_request
+ * callbacks.
+ */
+static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
+{
+	struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl);
+
+	if (chan->idx == 0) {
+		chan->ipc->ops->handle_reply(chan->ipc);
+	} else {
+		chan->ipc->ops->handle_request(chan->ipc);
+		imx_dsp_ring_doorbell(chan->ipc, 1);
+	}
+}
+
+static int imx_dsp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct imx_dsp_ipc *dsp_ipc;
+	struct imx_dsp_chan *dsp_chan;
+	struct mbox_client *cl;
+	char *chan_name;
+	int ret;
+	int i, j;
+
+	dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
+	if (!dsp_ipc)
+		return -ENOMEM;
+
+	for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
+		if (i < 2)
+			chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
+		else
+			chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
+
+		if (!chan_name)
+			return -ENOMEM;
+
+		dsp_chan = &dsp_ipc->chans[i];
+		cl = &dsp_chan->cl;
+		cl->dev = dev;
+		cl->tx_block = false;
+		cl->knows_txdone = true;
+		cl->rx_callback = imx_dsp_handle_rx;
+
+		dsp_chan->ipc = dsp_ipc;
+		dsp_chan->idx = i % 2;
+		dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
+		if (IS_ERR(dsp_chan->ch)) {
+			ret = PTR_ERR(dsp_chan->ch);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Failed to request mbox chan %s ret %d\n",
+					chan_name, ret);
+			goto out;
+		}
+
+		dev_dbg(dev, "request mbox chan %s\n", chan_name);
+		/* chan_name is not used anymore by framework */
+		kfree(chan_name);
+	}
+
+	dsp_ipc->dev = dev;
+
+	dev_set_drvdata(dev, dsp_ipc);
+
+	dev_info(dev, "NXP i.MX DSP IPC initialized\n");
+
+	return devm_of_platform_populate(dev);
+out:
+	kfree(chan_name);
+	for (j = 0; j < i; j++) {
+		dsp_chan = &dsp_ipc->chans[j];
+		mbox_free_channel(dsp_chan->ch);
+	}
+
+	return ret;
+}
+
+static const struct of_device_id imx_dsp_match[] = {
+	{ .compatible = "fsl,imx8qxp-dsp", },
+	{ /* Sentinel */ }
+};
+
+static struct platform_driver imx_dsp_driver = {
+	.driver = {
+		.name = "imx-dsp",
+		.of_match_table = imx_dsp_match,
+	},
+	.probe = imx_dsp_probe,
+};
+builtin_platform_driver(imx_dsp_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
+MODULE_DESCRIPTION("IMX DSP IPC protocol driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h
new file mode 100644
index 000000000000..7562099c9e46
--- /dev/null
+++ b/include/linux/firmware/imx/dsp.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 NXP
+ *
+ * Header file for the DSP IPC implementation
+ */
+
+#ifndef _IMX_DSP_IPC_H
+#define _IMX_DSP_IPC_H
+
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/mailbox_client.h>
+
+#define DSP_MU_CHAN_NUM		4
+
+struct imx_dsp_chan {
+	struct imx_dsp_ipc *ipc;
+	struct mbox_client cl;
+	struct mbox_chan *ch;
+	char *name;
+	int idx;
+};
+
+struct imx_dsp_ops {
+	void (*handle_reply)(struct imx_dsp_ipc *ipc);
+	void (*handle_request)(struct imx_dsp_ipc *ipc);
+};
+
+struct imx_dsp_ipc {
+	/* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */
+	struct imx_dsp_chan chans[DSP_MU_CHAN_NUM];
+	struct device *dev;
+	struct imx_dsp_ops *ops;
+	void *private_data;
+};
+
+static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data)
+{
+	if (!ipc)
+		return;
+
+	ipc->private_data = data;
+}
+
+static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc)
+{
+	if (!ipc)
+		return NULL;
+
+	return ipc->private_data;
+}
+
+#if IS_ENABLED(CONFIG_IMX_DSP)
+
+int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx);
+
+#else
+
+static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc,
+					unsigned int chan_idx)
+{
+	return -ENOTSUPP;
+}
+
+#endif
+#endif /* _IMX_DSP_IPC_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] dt-bindings: dsp: fsl: Add DSP IPC binding support
  2019-06-27  8:12 [PATCH v2 0/2] Add support for DSP IPC protocol driver Daniel Baluta
  2019-06-27  8:12 ` [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface Daniel Baluta
@ 2019-06-27  8:12 ` Daniel Baluta
  1 sibling, 0 replies; 6+ messages in thread
From: Daniel Baluta @ 2019-06-27  8:12 UTC (permalink / raw)
  To: shawnguo, robh+dt, o.rempel
  Cc: s.hauer, S.j. Wang, festevam, dl-linux-imx, Aisheng Dong,
	Anson Huang, linux-kernel, linux-arm-kernel, mark.rutland,
	devicetree, Daniel Baluta

DSP IPC is the layer that allows the Host CPU to communicate
with DSP firmware.
DSP is part of some i.MX8 boards (e.g i.MX8QM, i.MX8QXP)

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
 .../devicetree/bindings/dsp/fsl,dsp_ipc.yaml  | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dsp/fsl,dsp_ipc.yaml

diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp_ipc.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp_ipc.yaml
new file mode 100644
index 000000000000..1cbf5d25b258
--- /dev/null
+++ b/Documentation/devicetree/bindings/dsp/fsl,dsp_ipc.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/freescale/fsl,dsp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX8 IPC DSP interface
+
+maintainers:
+  - Daniel Baluta <daniel.baluta@nxp.com>
+
+description: |
+  IPC communication layer between Host CPU and DSP on NXP i.MX8 platforms
+
+properties:
+  compatible:
+    enum:
+      - fsl,imx8qxp-dsp
+
+  mboxes:
+    description:
+      List of <&phandle type channel> - 2 channels for TXDB, 2 channels for RXDB
+      (see mailbox/fsl,mu.txt)
+    maxItems: 4
+
+  mbox-names:
+    items:
+      - const: txdb0
+      - const: txdb1
+      - const: rxdb0
+      - const: rxdb1
+
+required:
+  - compatible
+  - mboxes
+  - mbox-names
+
+examples:
+  - |
+    dsp_ipc {
+      compatbile = "fsl,imx8qxp-dsp";
+      mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
+      mboxes = <&lsio_mu13 2 0>, <&lsio_mu13 2 1>, <&lsio_mu13 3 0>, <&lsio_mu13 3 1>;
+    };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface
  2019-06-27  8:12 ` [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface Daniel Baluta
@ 2019-07-09  5:48   ` Daniel Baluta
  2019-07-09 12:02     ` Oleksij Rempel
  0 siblings, 1 reply; 6+ messages in thread
From: Daniel Baluta @ 2019-07-09  5:48 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: shawnguo, robh+dt, o.rempel, s.hauer, S.j. Wang, festevam,
	dl-linux-imx, Aisheng Dong, Anson Huang, linux-kernel,
	linux-arm-kernel, mark.rutland, devicetree

Hi Oleksij,

Any comments on this?


On Thu, Jun 27, 2019 at 11:14 AM Daniel Baluta <daniel.baluta@nxp.com> wrote:
>
> Some of i.MX8 processors (e.g i.MX8QM, i.MX8QXP) contain
> the Tensilica HiFi4 DSP for advanced pre- and post-audio
> processing.
>
> The communication between Host CPU and DSP firmware is
> taking place using a shared memory area for message passing
> and a dedicated Messaging Unit for notifications.
>
> DSP IPC protocol driver offers a doorbell interface using
> imx-mailbox API.
>
> We use 4 MU channels (2 x TXDB, 2 x RXDB) to implement a
> request-reply protocol.
>
> Connection 0 (txdb0, rxdb0):
>         - Host writes messasge to shared memory [SHMEM]
>         - Host sends a request [MU]
>         - DSP handles request [SHMEM]
>         - DSP sends reply [MU]
>
> Connection 1 (txdb1, rxdb1):
>         - DSP writes a message to shared memory [SHMEM]
>         - DSP sends a request [MU]
>         - Host handles request [SHMEM]
>         - Host sends reply [MU]
>
> The protocol driver will be used by a Host client to
> communicate with the DSP. First client will be the i.MX8
> part from Sound Open Firmware infrastructure.
>
> The protocol drivers offers the following interface:
>
> On Tx:
>    - imx_dsp_ring_doorbell, will be called to notify the DSP
>    that it needs to handle a request.
>
> On Rx:
>    - clients need to provide two callbacks:
>         .handle_reply
>         .handle_request
>   - the callbacks will be used by the protocol driver on
>     notification arrival from DSP.
>
> Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
> ---
>  drivers/firmware/imx/Kconfig     |  11 +++
>  drivers/firmware/imx/Makefile    |   1 +
>  drivers/firmware/imx/imx-dsp.c   | 142 +++++++++++++++++++++++++++++++
>  include/linux/firmware/imx/dsp.h |  67 +++++++++++++++
>  4 files changed, 221 insertions(+)
>  create mode 100644 drivers/firmware/imx/imx-dsp.c
>  create mode 100644 include/linux/firmware/imx/dsp.h
>
> diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
> index 42b566f8903f..ddb241708c31 100644
> --- a/drivers/firmware/imx/Kconfig
> +++ b/drivers/firmware/imx/Kconfig
> @@ -1,4 +1,15 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> +config IMX_DSP
> +       bool "IMX DSP Protocol driver"
> +       depends on IMX_MBOX
> +       help
> +         This enables DSP IPC protocol between host CPU (Linux)
> +         and the firmware running on DSP.
> +         DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP).
> +
> +         It acts like a doorbell. Client might use shared memory to
> +         exchange information with DSP side.
> +
>  config IMX_SCU
>         bool "IMX SCU Protocol driver"
>         depends on IMX_MBOX
> diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
> index 802c4ad8e8f9..08bc9ddfbdfb 100644
> --- a/drivers/firmware/imx/Makefile
> +++ b/drivers/firmware/imx/Makefile
> @@ -1,3 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_IMX_DSP)          += imx-dsp.o
>  obj-$(CONFIG_IMX_SCU)          += imx-scu.o misc.o imx-scu-irq.o
>  obj-$(CONFIG_IMX_SCU_PD)       += scu-pd.o
> diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
> new file mode 100644
> index 000000000000..c4d34a2fbff3
> --- /dev/null
> +++ b/drivers/firmware/imx/imx-dsp.c
> @@ -0,0 +1,142 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2019 NXP
> + *  Author: Daniel Baluta <daniel.baluta@nxp.com>
> + *
> + * Implementation of the DSP IPC interface (host side)
> + */
> +
> +#include <linux/firmware/imx/dsp.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_client.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +/*
> + * imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP)
> + *
> + * @dsp: DSP IPC handle
> + * @chan_idx: index of the channel where to trigger the interrupt
> + *
> + * Returns non-negative value for success, negative value for error
> + */
> +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx)
> +{
> +       int ret;
> +       struct imx_dsp_chan *dsp_chan;
> +
> +       if (idx >= DSP_MU_CHAN_NUM)
> +               return -EINVAL;
> +
> +       dsp_chan = &ipc->chans[idx];
> +       ret = mbox_send_message(dsp_chan->ch, NULL);
> +       if (ret < 0)
> +               return ret;
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(imx_dsp_ring_doorbell);
> +
> +/*
> + * imx_dsp_handle_rx - rx callback used by imx mailbox
> + *
> + * @c: mbox client
> + * @msg: message received
> + *
> + * Users of DSP IPC will need to privde handle_reply and handle_request
> + * callbacks.
> + */
> +static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
> +{
> +       struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl);
> +
> +       if (chan->idx == 0) {
> +               chan->ipc->ops->handle_reply(chan->ipc);
> +       } else {
> +               chan->ipc->ops->handle_request(chan->ipc);
> +               imx_dsp_ring_doorbell(chan->ipc, 1);
> +       }
> +}
> +
> +static int imx_dsp_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct imx_dsp_ipc *dsp_ipc;
> +       struct imx_dsp_chan *dsp_chan;
> +       struct mbox_client *cl;
> +       char *chan_name;
> +       int ret;
> +       int i, j;
> +
> +       dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
> +       if (!dsp_ipc)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
> +               if (i < 2)
> +                       chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
> +               else
> +                       chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
> +
> +               if (!chan_name)
> +                       return -ENOMEM;
> +
> +               dsp_chan = &dsp_ipc->chans[i];
> +               cl = &dsp_chan->cl;
> +               cl->dev = dev;
> +               cl->tx_block = false;
> +               cl->knows_txdone = true;
> +               cl->rx_callback = imx_dsp_handle_rx;
> +
> +               dsp_chan->ipc = dsp_ipc;
> +               dsp_chan->idx = i % 2;
> +               dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
> +               if (IS_ERR(dsp_chan->ch)) {
> +                       ret = PTR_ERR(dsp_chan->ch);
> +                       if (ret != -EPROBE_DEFER)
> +                               dev_err(dev, "Failed to request mbox chan %s ret %d\n",
> +                                       chan_name, ret);
> +                       goto out;
> +               }
> +
> +               dev_dbg(dev, "request mbox chan %s\n", chan_name);
> +               /* chan_name is not used anymore by framework */
> +               kfree(chan_name);
> +       }
> +
> +       dsp_ipc->dev = dev;
> +
> +       dev_set_drvdata(dev, dsp_ipc);
> +
> +       dev_info(dev, "NXP i.MX DSP IPC initialized\n");
> +
> +       return devm_of_platform_populate(dev);
> +out:
> +       kfree(chan_name);
> +       for (j = 0; j < i; j++) {
> +               dsp_chan = &dsp_ipc->chans[j];
> +               mbox_free_channel(dsp_chan->ch);
> +       }
> +
> +       return ret;
> +}
> +
> +static const struct of_device_id imx_dsp_match[] = {
> +       { .compatible = "fsl,imx8qxp-dsp", },
> +       { /* Sentinel */ }
> +};
> +
> +static struct platform_driver imx_dsp_driver = {
> +       .driver = {
> +               .name = "imx-dsp",
> +               .of_match_table = imx_dsp_match,
> +       },
> +       .probe = imx_dsp_probe,
> +};
> +builtin_platform_driver(imx_dsp_driver);
> +
> +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
> +MODULE_DESCRIPTION("IMX DSP IPC protocol driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h
> new file mode 100644
> index 000000000000..7562099c9e46
> --- /dev/null
> +++ b/include/linux/firmware/imx/dsp.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2019 NXP
> + *
> + * Header file for the DSP IPC implementation
> + */
> +
> +#ifndef _IMX_DSP_IPC_H
> +#define _IMX_DSP_IPC_H
> +
> +#include <linux/device.h>
> +#include <linux/types.h>
> +#include <linux/mailbox_client.h>
> +
> +#define DSP_MU_CHAN_NUM                4
> +
> +struct imx_dsp_chan {
> +       struct imx_dsp_ipc *ipc;
> +       struct mbox_client cl;
> +       struct mbox_chan *ch;
> +       char *name;
> +       int idx;
> +};
> +
> +struct imx_dsp_ops {
> +       void (*handle_reply)(struct imx_dsp_ipc *ipc);
> +       void (*handle_request)(struct imx_dsp_ipc *ipc);
> +};
> +
> +struct imx_dsp_ipc {
> +       /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */
> +       struct imx_dsp_chan chans[DSP_MU_CHAN_NUM];
> +       struct device *dev;
> +       struct imx_dsp_ops *ops;
> +       void *private_data;
> +};
> +
> +static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data)
> +{
> +       if (!ipc)
> +               return;
> +
> +       ipc->private_data = data;
> +}
> +
> +static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc)
> +{
> +       if (!ipc)
> +               return NULL;
> +
> +       return ipc->private_data;
> +}
> +
> +#if IS_ENABLED(CONFIG_IMX_DSP)
> +
> +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx);
> +
> +#else
> +
> +static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc,
> +                                       unsigned int chan_idx)
> +{
> +       return -ENOTSUPP;
> +}
> +
> +#endif
> +#endif /* _IMX_DSP_IPC_H */
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface
  2019-07-09  5:48   ` Daniel Baluta
@ 2019-07-09 12:02     ` Oleksij Rempel
  2019-07-18  6:40       ` Daniel Baluta
  0 siblings, 1 reply; 6+ messages in thread
From: Oleksij Rempel @ 2019-07-09 12:02 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Daniel Baluta, shawnguo, robh+dt, s.hauer, S.j. Wang, festevam,
	dl-linux-imx, Aisheng Dong, Anson Huang, linux-kernel,
	linux-arm-kernel, mark.rutland, devicetree

On Tue, Jul 09, 2019 at 08:48:20AM +0300, Daniel Baluta wrote:
> Hi Oleksij,
> 
> Any comments on this?

Looks good for me. All my suggestions was fixed.

Reviewed-by: <o.rempel@pengutronix.de>

> On Thu, Jun 27, 2019 at 11:14 AM Daniel Baluta <daniel.baluta@nxp.com> wrote:
> >
> > Some of i.MX8 processors (e.g i.MX8QM, i.MX8QXP) contain
> > the Tensilica HiFi4 DSP for advanced pre- and post-audio
> > processing.
> >
> > The communication between Host CPU and DSP firmware is
> > taking place using a shared memory area for message passing
> > and a dedicated Messaging Unit for notifications.
> >
> > DSP IPC protocol driver offers a doorbell interface using
> > imx-mailbox API.
> >
> > We use 4 MU channels (2 x TXDB, 2 x RXDB) to implement a
> > request-reply protocol.
> >
> > Connection 0 (txdb0, rxdb0):
> >         - Host writes messasge to shared memory [SHMEM]
> >         - Host sends a request [MU]
> >         - DSP handles request [SHMEM]
> >         - DSP sends reply [MU]
> >
> > Connection 1 (txdb1, rxdb1):
> >         - DSP writes a message to shared memory [SHMEM]
> >         - DSP sends a request [MU]
> >         - Host handles request [SHMEM]
> >         - Host sends reply [MU]
> >
> > The protocol driver will be used by a Host client to
> > communicate with the DSP. First client will be the i.MX8
> > part from Sound Open Firmware infrastructure.
> >
> > The protocol drivers offers the following interface:
> >
> > On Tx:
> >    - imx_dsp_ring_doorbell, will be called to notify the DSP
> >    that it needs to handle a request.
> >
> > On Rx:
> >    - clients need to provide two callbacks:
> >         .handle_reply
> >         .handle_request
> >   - the callbacks will be used by the protocol driver on
> >     notification arrival from DSP.
> >
> > Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
> > ---
> >  drivers/firmware/imx/Kconfig     |  11 +++
> >  drivers/firmware/imx/Makefile    |   1 +
> >  drivers/firmware/imx/imx-dsp.c   | 142 +++++++++++++++++++++++++++++++
> >  include/linux/firmware/imx/dsp.h |  67 +++++++++++++++
> >  4 files changed, 221 insertions(+)
> >  create mode 100644 drivers/firmware/imx/imx-dsp.c
> >  create mode 100644 include/linux/firmware/imx/dsp.h
> >
> > diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
> > index 42b566f8903f..ddb241708c31 100644
> > --- a/drivers/firmware/imx/Kconfig
> > +++ b/drivers/firmware/imx/Kconfig
> > @@ -1,4 +1,15 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> > +config IMX_DSP
> > +       bool "IMX DSP Protocol driver"
> > +       depends on IMX_MBOX
> > +       help
> > +         This enables DSP IPC protocol between host CPU (Linux)
> > +         and the firmware running on DSP.
> > +         DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP).
> > +
> > +         It acts like a doorbell. Client might use shared memory to
> > +         exchange information with DSP side.
> > +
> >  config IMX_SCU
> >         bool "IMX SCU Protocol driver"
> >         depends on IMX_MBOX
> > diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
> > index 802c4ad8e8f9..08bc9ddfbdfb 100644
> > --- a/drivers/firmware/imx/Makefile
> > +++ b/drivers/firmware/imx/Makefile
> > @@ -1,3 +1,4 @@
> >  # SPDX-License-Identifier: GPL-2.0
> > +obj-$(CONFIG_IMX_DSP)          += imx-dsp.o
> >  obj-$(CONFIG_IMX_SCU)          += imx-scu.o misc.o imx-scu-irq.o
> >  obj-$(CONFIG_IMX_SCU_PD)       += scu-pd.o
> > diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
> > new file mode 100644
> > index 000000000000..c4d34a2fbff3
> > --- /dev/null
> > +++ b/drivers/firmware/imx/imx-dsp.c
> > @@ -0,0 +1,142 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2019 NXP
> > + *  Author: Daniel Baluta <daniel.baluta@nxp.com>
> > + *
> > + * Implementation of the DSP IPC interface (host side)
> > + */
> > +
> > +#include <linux/firmware/imx/dsp.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mailbox_client.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +
> > +/*
> > + * imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP)
> > + *
> > + * @dsp: DSP IPC handle
> > + * @chan_idx: index of the channel where to trigger the interrupt
> > + *
> > + * Returns non-negative value for success, negative value for error
> > + */
> > +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx)
> > +{
> > +       int ret;
> > +       struct imx_dsp_chan *dsp_chan;
> > +
> > +       if (idx >= DSP_MU_CHAN_NUM)
> > +               return -EINVAL;
> > +
> > +       dsp_chan = &ipc->chans[idx];
> > +       ret = mbox_send_message(dsp_chan->ch, NULL);
> > +       if (ret < 0)
> > +               return ret;
> > +
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL(imx_dsp_ring_doorbell);
> > +
> > +/*
> > + * imx_dsp_handle_rx - rx callback used by imx mailbox
> > + *
> > + * @c: mbox client
> > + * @msg: message received
> > + *
> > + * Users of DSP IPC will need to privde handle_reply and handle_request
> > + * callbacks.
> > + */
> > +static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
> > +{
> > +       struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl);
> > +
> > +       if (chan->idx == 0) {
> > +               chan->ipc->ops->handle_reply(chan->ipc);
> > +       } else {
> > +               chan->ipc->ops->handle_request(chan->ipc);
> > +               imx_dsp_ring_doorbell(chan->ipc, 1);
> > +       }
> > +}
> > +
> > +static int imx_dsp_probe(struct platform_device *pdev)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct imx_dsp_ipc *dsp_ipc;
> > +       struct imx_dsp_chan *dsp_chan;
> > +       struct mbox_client *cl;
> > +       char *chan_name;
> > +       int ret;
> > +       int i, j;
> > +
> > +       dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
> > +       if (!dsp_ipc)
> > +               return -ENOMEM;
> > +
> > +       for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
> > +               if (i < 2)
> > +                       chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
> > +               else
> > +                       chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
> > +
> > +               if (!chan_name)
> > +                       return -ENOMEM;
> > +
> > +               dsp_chan = &dsp_ipc->chans[i];
> > +               cl = &dsp_chan->cl;
> > +               cl->dev = dev;
> > +               cl->tx_block = false;
> > +               cl->knows_txdone = true;
> > +               cl->rx_callback = imx_dsp_handle_rx;
> > +
> > +               dsp_chan->ipc = dsp_ipc;
> > +               dsp_chan->idx = i % 2;
> > +               dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
> > +               if (IS_ERR(dsp_chan->ch)) {
> > +                       ret = PTR_ERR(dsp_chan->ch);
> > +                       if (ret != -EPROBE_DEFER)
> > +                               dev_err(dev, "Failed to request mbox chan %s ret %d\n",
> > +                                       chan_name, ret);
> > +                       goto out;
> > +               }
> > +
> > +               dev_dbg(dev, "request mbox chan %s\n", chan_name);
> > +               /* chan_name is not used anymore by framework */
> > +               kfree(chan_name);
> > +       }
> > +
> > +       dsp_ipc->dev = dev;
> > +
> > +       dev_set_drvdata(dev, dsp_ipc);
> > +
> > +       dev_info(dev, "NXP i.MX DSP IPC initialized\n");
> > +
> > +       return devm_of_platform_populate(dev);
> > +out:
> > +       kfree(chan_name);
> > +       for (j = 0; j < i; j++) {
> > +               dsp_chan = &dsp_ipc->chans[j];
> > +               mbox_free_channel(dsp_chan->ch);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static const struct of_device_id imx_dsp_match[] = {
> > +       { .compatible = "fsl,imx8qxp-dsp", },
> > +       { /* Sentinel */ }
> > +};
> > +
> > +static struct platform_driver imx_dsp_driver = {
> > +       .driver = {
> > +               .name = "imx-dsp",
> > +               .of_match_table = imx_dsp_match,
> > +       },
> > +       .probe = imx_dsp_probe,
> > +};
> > +builtin_platform_driver(imx_dsp_driver);
> > +
> > +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
> > +MODULE_DESCRIPTION("IMX DSP IPC protocol driver");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h
> > new file mode 100644
> > index 000000000000..7562099c9e46
> > --- /dev/null
> > +++ b/include/linux/firmware/imx/dsp.h
> > @@ -0,0 +1,67 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright 2019 NXP
> > + *
> > + * Header file for the DSP IPC implementation
> > + */
> > +
> > +#ifndef _IMX_DSP_IPC_H
> > +#define _IMX_DSP_IPC_H
> > +
> > +#include <linux/device.h>
> > +#include <linux/types.h>
> > +#include <linux/mailbox_client.h>
> > +
> > +#define DSP_MU_CHAN_NUM                4
> > +
> > +struct imx_dsp_chan {
> > +       struct imx_dsp_ipc *ipc;
> > +       struct mbox_client cl;
> > +       struct mbox_chan *ch;
> > +       char *name;
> > +       int idx;
> > +};
> > +
> > +struct imx_dsp_ops {
> > +       void (*handle_reply)(struct imx_dsp_ipc *ipc);
> > +       void (*handle_request)(struct imx_dsp_ipc *ipc);
> > +};
> > +
> > +struct imx_dsp_ipc {
> > +       /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */
> > +       struct imx_dsp_chan chans[DSP_MU_CHAN_NUM];
> > +       struct device *dev;
> > +       struct imx_dsp_ops *ops;
> > +       void *private_data;
> > +};
> > +
> > +static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data)
> > +{
> > +       if (!ipc)
> > +               return;
> > +
> > +       ipc->private_data = data;
> > +}
> > +
> > +static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc)
> > +{
> > +       if (!ipc)
> > +               return NULL;
> > +
> > +       return ipc->private_data;
> > +}
> > +
> > +#if IS_ENABLED(CONFIG_IMX_DSP)
> > +
> > +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx);
> > +
> > +#else
> > +
> > +static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc,
> > +                                       unsigned int chan_idx)
> > +{
> > +       return -ENOTSUPP;
> > +}
> > +
> > +#endif
> > +#endif /* _IMX_DSP_IPC_H */
> > --
> > 2.17.1
> >
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface
  2019-07-09 12:02     ` Oleksij Rempel
@ 2019-07-18  6:40       ` Daniel Baluta
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Baluta @ 2019-07-18  6:40 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Daniel Baluta, shawnguo, robh+dt, s.hauer, S.j. Wang, festevam,
	dl-linux-imx, Aisheng Dong, Anson Huang, linux-kernel,
	linux-arm-kernel, mark.rutland, devicetree

I just made some minor changes and will send the patch right now.
Shawn please skip this.

On Tue, Jul 9, 2019 at 3:02 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>
> On Tue, Jul 09, 2019 at 08:48:20AM +0300, Daniel Baluta wrote:
> > Hi Oleksij,
> >
> > Any comments on this?
>
> Looks good for me. All my suggestions was fixed.
>
> Reviewed-by: <o.rempel@pengutronix.de>
>
> > On Thu, Jun 27, 2019 at 11:14 AM Daniel Baluta <daniel.baluta@nxp.com> wrote:
> > >
> > > Some of i.MX8 processors (e.g i.MX8QM, i.MX8QXP) contain
> > > the Tensilica HiFi4 DSP for advanced pre- and post-audio
> > > processing.
> > >
> > > The communication between Host CPU and DSP firmware is
> > > taking place using a shared memory area for message passing
> > > and a dedicated Messaging Unit for notifications.
> > >
> > > DSP IPC protocol driver offers a doorbell interface using
> > > imx-mailbox API.
> > >
> > > We use 4 MU channels (2 x TXDB, 2 x RXDB) to implement a
> > > request-reply protocol.
> > >
> > > Connection 0 (txdb0, rxdb0):
> > >         - Host writes messasge to shared memory [SHMEM]
> > >         - Host sends a request [MU]
> > >         - DSP handles request [SHMEM]
> > >         - DSP sends reply [MU]
> > >
> > > Connection 1 (txdb1, rxdb1):
> > >         - DSP writes a message to shared memory [SHMEM]
> > >         - DSP sends a request [MU]
> > >         - Host handles request [SHMEM]
> > >         - Host sends reply [MU]
> > >
> > > The protocol driver will be used by a Host client to
> > > communicate with the DSP. First client will be the i.MX8
> > > part from Sound Open Firmware infrastructure.
> > >
> > > The protocol drivers offers the following interface:
> > >
> > > On Tx:
> > >    - imx_dsp_ring_doorbell, will be called to notify the DSP
> > >    that it needs to handle a request.
> > >
> > > On Rx:
> > >    - clients need to provide two callbacks:
> > >         .handle_reply
> > >         .handle_request
> > >   - the callbacks will be used by the protocol driver on
> > >     notification arrival from DSP.
> > >
> > > Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
> > > ---
> > >  drivers/firmware/imx/Kconfig     |  11 +++
> > >  drivers/firmware/imx/Makefile    |   1 +
> > >  drivers/firmware/imx/imx-dsp.c   | 142 +++++++++++++++++++++++++++++++
> > >  include/linux/firmware/imx/dsp.h |  67 +++++++++++++++
> > >  4 files changed, 221 insertions(+)
> > >  create mode 100644 drivers/firmware/imx/imx-dsp.c
> > >  create mode 100644 include/linux/firmware/imx/dsp.h
> > >
> > > diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
> > > index 42b566f8903f..ddb241708c31 100644
> > > --- a/drivers/firmware/imx/Kconfig
> > > +++ b/drivers/firmware/imx/Kconfig
> > > @@ -1,4 +1,15 @@
> > >  # SPDX-License-Identifier: GPL-2.0-only
> > > +config IMX_DSP
> > > +       bool "IMX DSP Protocol driver"
> > > +       depends on IMX_MBOX
> > > +       help
> > > +         This enables DSP IPC protocol between host CPU (Linux)
> > > +         and the firmware running on DSP.
> > > +         DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP).
> > > +
> > > +         It acts like a doorbell. Client might use shared memory to
> > > +         exchange information with DSP side.
> > > +
> > >  config IMX_SCU
> > >         bool "IMX SCU Protocol driver"
> > >         depends on IMX_MBOX
> > > diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
> > > index 802c4ad8e8f9..08bc9ddfbdfb 100644
> > > --- a/drivers/firmware/imx/Makefile
> > > +++ b/drivers/firmware/imx/Makefile
> > > @@ -1,3 +1,4 @@
> > >  # SPDX-License-Identifier: GPL-2.0
> > > +obj-$(CONFIG_IMX_DSP)          += imx-dsp.o
> > >  obj-$(CONFIG_IMX_SCU)          += imx-scu.o misc.o imx-scu-irq.o
> > >  obj-$(CONFIG_IMX_SCU_PD)       += scu-pd.o
> > > diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
> > > new file mode 100644
> > > index 000000000000..c4d34a2fbff3
> > > --- /dev/null
> > > +++ b/drivers/firmware/imx/imx-dsp.c
> > > @@ -0,0 +1,142 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/*
> > > + * Copyright 2019 NXP
> > > + *  Author: Daniel Baluta <daniel.baluta@nxp.com>
> > > + *
> > > + * Implementation of the DSP IPC interface (host side)
> > > + */
> > > +
> > > +#include <linux/firmware/imx/dsp.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/mailbox_client.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of_platform.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/slab.h>
> > > +
> > > +/*
> > > + * imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP)
> > > + *
> > > + * @dsp: DSP IPC handle
> > > + * @chan_idx: index of the channel where to trigger the interrupt
> > > + *
> > > + * Returns non-negative value for success, negative value for error
> > > + */
> > > +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx)
> > > +{
> > > +       int ret;
> > > +       struct imx_dsp_chan *dsp_chan;
> > > +
> > > +       if (idx >= DSP_MU_CHAN_NUM)
> > > +               return -EINVAL;
> > > +
> > > +       dsp_chan = &ipc->chans[idx];
> > > +       ret = mbox_send_message(dsp_chan->ch, NULL);
> > > +       if (ret < 0)
> > > +               return ret;
> > > +
> > > +       return 0;
> > > +}
> > > +EXPORT_SYMBOL(imx_dsp_ring_doorbell);
> > > +
> > > +/*
> > > + * imx_dsp_handle_rx - rx callback used by imx mailbox
> > > + *
> > > + * @c: mbox client
> > > + * @msg: message received
> > > + *
> > > + * Users of DSP IPC will need to privde handle_reply and handle_request
> > > + * callbacks.
> > > + */
> > > +static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
> > > +{
> > > +       struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl);
> > > +
> > > +       if (chan->idx == 0) {
> > > +               chan->ipc->ops->handle_reply(chan->ipc);
> > > +       } else {
> > > +               chan->ipc->ops->handle_request(chan->ipc);
> > > +               imx_dsp_ring_doorbell(chan->ipc, 1);
> > > +       }
> > > +}
> > > +
> > > +static int imx_dsp_probe(struct platform_device *pdev)
> > > +{
> > > +       struct device *dev = &pdev->dev;
> > > +       struct imx_dsp_ipc *dsp_ipc;
> > > +       struct imx_dsp_chan *dsp_chan;
> > > +       struct mbox_client *cl;
> > > +       char *chan_name;
> > > +       int ret;
> > > +       int i, j;
> > > +
> > > +       dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
> > > +       if (!dsp_ipc)
> > > +               return -ENOMEM;
> > > +
> > > +       for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
> > > +               if (i < 2)
> > > +                       chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
> > > +               else
> > > +                       chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
> > > +
> > > +               if (!chan_name)
> > > +                       return -ENOMEM;
> > > +
> > > +               dsp_chan = &dsp_ipc->chans[i];
> > > +               cl = &dsp_chan->cl;
> > > +               cl->dev = dev;
> > > +               cl->tx_block = false;
> > > +               cl->knows_txdone = true;
> > > +               cl->rx_callback = imx_dsp_handle_rx;
> > > +
> > > +               dsp_chan->ipc = dsp_ipc;
> > > +               dsp_chan->idx = i % 2;
> > > +               dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
> > > +               if (IS_ERR(dsp_chan->ch)) {
> > > +                       ret = PTR_ERR(dsp_chan->ch);
> > > +                       if (ret != -EPROBE_DEFER)
> > > +                               dev_err(dev, "Failed to request mbox chan %s ret %d\n",
> > > +                                       chan_name, ret);
> > > +                       goto out;
> > > +               }
> > > +
> > > +               dev_dbg(dev, "request mbox chan %s\n", chan_name);
> > > +               /* chan_name is not used anymore by framework */
> > > +               kfree(chan_name);
> > > +       }
> > > +
> > > +       dsp_ipc->dev = dev;
> > > +
> > > +       dev_set_drvdata(dev, dsp_ipc);
> > > +
> > > +       dev_info(dev, "NXP i.MX DSP IPC initialized\n");
> > > +
> > > +       return devm_of_platform_populate(dev);
> > > +out:
> > > +       kfree(chan_name);
> > > +       for (j = 0; j < i; j++) {
> > > +               dsp_chan = &dsp_ipc->chans[j];
> > > +               mbox_free_channel(dsp_chan->ch);
> > > +       }
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct of_device_id imx_dsp_match[] = {
> > > +       { .compatible = "fsl,imx8qxp-dsp", },
> > > +       { /* Sentinel */ }
> > > +};
> > > +
> > > +static struct platform_driver imx_dsp_driver = {
> > > +       .driver = {
> > > +               .name = "imx-dsp",
> > > +               .of_match_table = imx_dsp_match,
> > > +       },
> > > +       .probe = imx_dsp_probe,
> > > +};
> > > +builtin_platform_driver(imx_dsp_driver);
> > > +
> > > +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
> > > +MODULE_DESCRIPTION("IMX DSP IPC protocol driver");
> > > +MODULE_LICENSE("GPL v2");
> > > diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h
> > > new file mode 100644
> > > index 000000000000..7562099c9e46
> > > --- /dev/null
> > > +++ b/include/linux/firmware/imx/dsp.h
> > > @@ -0,0 +1,67 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +/*
> > > + * Copyright 2019 NXP
> > > + *
> > > + * Header file for the DSP IPC implementation
> > > + */
> > > +
> > > +#ifndef _IMX_DSP_IPC_H
> > > +#define _IMX_DSP_IPC_H
> > > +
> > > +#include <linux/device.h>
> > > +#include <linux/types.h>
> > > +#include <linux/mailbox_client.h>
> > > +
> > > +#define DSP_MU_CHAN_NUM                4
> > > +
> > > +struct imx_dsp_chan {
> > > +       struct imx_dsp_ipc *ipc;
> > > +       struct mbox_client cl;
> > > +       struct mbox_chan *ch;
> > > +       char *name;
> > > +       int idx;
> > > +};
> > > +
> > > +struct imx_dsp_ops {
> > > +       void (*handle_reply)(struct imx_dsp_ipc *ipc);
> > > +       void (*handle_request)(struct imx_dsp_ipc *ipc);
> > > +};
> > > +
> > > +struct imx_dsp_ipc {
> > > +       /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */
> > > +       struct imx_dsp_chan chans[DSP_MU_CHAN_NUM];
> > > +       struct device *dev;
> > > +       struct imx_dsp_ops *ops;
> > > +       void *private_data;
> > > +};
> > > +
> > > +static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data)
> > > +{
> > > +       if (!ipc)
> > > +               return;
> > > +
> > > +       ipc->private_data = data;
> > > +}
> > > +
> > > +static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc)
> > > +{
> > > +       if (!ipc)
> > > +               return NULL;
> > > +
> > > +       return ipc->private_data;
> > > +}
> > > +
> > > +#if IS_ENABLED(CONFIG_IMX_DSP)
> > > +
> > > +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx);
> > > +
> > > +#else
> > > +
> > > +static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc,
> > > +                                       unsigned int chan_idx)
> > > +{
> > > +       return -ENOTSUPP;
> > > +}
> > > +
> > > +#endif
> > > +#endif /* _IMX_DSP_IPC_H */
> > > --
> > > 2.17.1
> > >
> >
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-07-18  6:40 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-27  8:12 [PATCH v2 0/2] Add support for DSP IPC protocol driver Daniel Baluta
2019-06-27  8:12 ` [PATCH v2 1/2] firmware: imx: Add DSP IPC protocol interface Daniel Baluta
2019-07-09  5:48   ` Daniel Baluta
2019-07-09 12:02     ` Oleksij Rempel
2019-07-18  6:40       ` Daniel Baluta
2019-06-27  8:12 ` [PATCH v2 2/2] dt-bindings: dsp: fsl: Add DSP IPC binding support Daniel Baluta

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).