Commit 7b972f38 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'imx-drivers-5.8' of...

Merge tag 'imx-drivers-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/drivers

i.MX drivers update for 5.8:

- Optimize imx-scu driver to use one TX and one RX instead of four for
  talking to SCU.
- Fix one possible message header corruption where the response is
  longer than the request.
- Move System Control defines into dt-bindings header, so that DT can
  use them as well.
- A couple of small fixups.

* tag 'imx-drivers-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
  firmware: imx: scu: Fix possible memory leak in imx_scu_probe()
  dt-bindings: firmware: imx: Add more system controls and PM clock types
  dt-bindings: firmware: imx: Move system control into dt-binding headfile
  firmware: imx: scu: Fix corruption of header
  firmware: imx-scu: Support one TX and one RX
  soc: imx8m: No need to put node when of_find_compatible_node() failed

Link: https://lore.kernel.org/r/20200523032516.11016-1-shawnguo@kernel.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents e26552c5 89f12d65
Loading
Loading
Loading
Loading
+48 −16
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@
 */

#include <linux/err.h>
#include <linux/firmware/imx/types.h>
#include <linux/firmware/imx/ipc.h>
#include <linux/firmware/imx/sci.h>
#include <linux/interrupt.h>
@@ -38,6 +37,7 @@ struct imx_sc_ipc {
	struct device *dev;
	struct mutex lock;
	struct completion done;
	bool fast_ipc;

	/* temporarily store the SCU msg */
	u32 *msg;
@@ -115,6 +115,7 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
	struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc;
	struct imx_sc_rpc_msg *hdr;
	u32 *data = msg;
	int i;

	if (!sc_ipc->msg) {
		dev_warn(sc_ipc->dev, "unexpected rx idx %d 0x%08x, ignore!\n",
@@ -122,6 +123,19 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
		return;
	}

	if (sc_ipc->fast_ipc) {
		hdr = msg;
		sc_ipc->rx_size = hdr->size;
		sc_ipc->msg[0] = *data++;

		for (i = 1; i < sc_ipc->rx_size; i++)
			sc_ipc->msg[i] = *data++;

		complete(&sc_ipc->done);

		return;
	}

	if (sc_chan->idx == 0) {
		hdr = msg;
		sc_ipc->rx_size = hdr->size;
@@ -143,20 +157,22 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)

static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
{
	struct imx_sc_rpc_msg *hdr = msg;
	struct imx_sc_rpc_msg hdr = *(struct imx_sc_rpc_msg *)msg;
	struct imx_sc_chan *sc_chan;
	u32 *data = msg;
	int ret;
	int size;
	int i;

	/* Check size */
	if (hdr->size > IMX_SC_RPC_MAX_MSG)
	if (hdr.size > IMX_SC_RPC_MAX_MSG)
		return -EINVAL;

	dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
		hdr->func, hdr->size);
	dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr.svc,
		hdr.func, hdr.size);

	for (i = 0; i < hdr->size; i++) {
	size = sc_ipc->fast_ipc ? 1 : hdr.size;
	for (i = 0; i < size; i++) {
		sc_chan = &sc_ipc->chans[i % 4];

		/*
@@ -168,8 +184,10 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
		 * Wait for tx_done before every send to ensure that no
		 * queueing happens at the mailbox channel level.
		 */
		if (!sc_ipc->fast_ipc) {
			wait_for_completion(&sc_chan->tx_done);
			reinit_completion(&sc_chan->tx_done);
		}

		ret = mbox_send_message(sc_chan->ch, &data[i]);
		if (ret < 0)
@@ -246,6 +264,8 @@ static int imx_scu_probe(struct platform_device *pdev)
	struct imx_sc_chan *sc_chan;
	struct mbox_client *cl;
	char *chan_name;
	struct of_phandle_args args;
	int num_channel;
	int ret;
	int i;

@@ -253,11 +273,20 @@ static int imx_scu_probe(struct platform_device *pdev)
	if (!sc_ipc)
		return -ENOMEM;

	for (i = 0; i < SCU_MU_CHAN_NUM; i++) {
		if (i < 4)
	ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
					 "#mbox-cells", 0, &args);
	if (ret)
		return ret;

	sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");

	num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
	for (i = 0; i < num_channel; i++) {
		if (i < num_channel / 2)
			chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
		else
			chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4);
			chan_name = kasprintf(GFP_KERNEL, "rx%d",
					      i - num_channel / 2);

		if (!chan_name)
			return -ENOMEM;
@@ -269,19 +298,22 @@ static int imx_scu_probe(struct platform_device *pdev)
		cl->knows_txdone = true;
		cl->rx_callback = imx_scu_rx_callback;

		if (!sc_ipc->fast_ipc) {
			/* Initial tx_done completion as "done" */
			cl->tx_done = imx_scu_tx_done;
			init_completion(&sc_chan->tx_done);
			complete(&sc_chan->tx_done);
		}

		sc_chan->sc_ipc = sc_ipc;
		sc_chan->idx = i % 4;
		sc_chan->idx = i % (num_channel / 2);
		sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
		if (IS_ERR(sc_chan->ch)) {
			ret = PTR_ERR(sc_chan->ch);
			if (ret != -EPROBE_DEFER)
				dev_err(dev, "Failed to request mbox chan %s ret %d\n",
					chan_name, ret);
			kfree(chan_name);
			return ret;
		}

+3 −4
Original line number Diff line number Diff line
@@ -53,11 +53,11 @@ static u32 __init imx8mq_soc_revision(void)
	struct device_node *np;
	void __iomem *ocotp_base;
	u32 magic;
	u32 rev = 0;
	u32 rev;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
	if (!np)
		goto out;
		return 0;

	ocotp_base = of_iomap(np, 0);
	WARN_ON(!ocotp_base);
@@ -78,9 +78,8 @@ static u32 __init imx8mq_soc_revision(void)
	soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);

	iounmap(ocotp_base);

out:
	of_node_put(np);

	return rev;
}

+1 −1
Original line number Diff line number Diff line
@@ -3,9 +3,9 @@
 * Copyright 2018-2020 NXP.
 */

#include <dt-bindings/firmware/imx/rsrc.h>
#include <linux/err.h>
#include <linux/firmware/imx/sci.h>
#include <linux/firmware/imx/types.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+84 −0
Original line number Diff line number Diff line
@@ -547,4 +547,88 @@
#define IMX_SC_R_ATTESTATION		545
#define IMX_SC_R_LAST			546

/*
 * Defines for SC PM CLK
 */
#define IMX_SC_PM_CLK_SLV_BUS		0	/* Slave bus clock */
#define IMX_SC_PM_CLK_MST_BUS		1	/* Master bus clock */
#define IMX_SC_PM_CLK_PER		2	/* Peripheral clock */
#define IMX_SC_PM_CLK_PHY		3	/* Phy clock */
#define IMX_SC_PM_CLK_MISC		4	/* Misc clock */
#define IMX_SC_PM_CLK_MISC0		0	/* Misc 0 clock */
#define IMX_SC_PM_CLK_MISC1		1	/* Misc 1 clock */
#define IMX_SC_PM_CLK_MISC2		2	/* Misc 2 clock */
#define IMX_SC_PM_CLK_MISC3		3	/* Misc 3 clock */
#define IMX_SC_PM_CLK_MISC4		4	/* Misc 4 clock */
#define IMX_SC_PM_CLK_CPU		2	/* CPU clock */
#define IMX_SC_PM_CLK_PLL		4	/* PLL */
#define IMX_SC_PM_CLK_BYPASS		4	/* Bypass clock */

/*
 * Defines for SC CONTROL
 */
#define IMX_SC_C_TEMP				0
#define IMX_SC_C_TEMP_HI			1
#define IMX_SC_C_TEMP_LOW			2
#define IMX_SC_C_PXL_LINK_MST1_ADDR		3
#define IMX_SC_C_PXL_LINK_MST2_ADDR		4
#define IMX_SC_C_PXL_LINK_MST_ENB		5
#define IMX_SC_C_PXL_LINK_MST1_ENB		6
#define IMX_SC_C_PXL_LINK_MST2_ENB		7
#define IMX_SC_C_PXL_LINK_SLV1_ADDR		8
#define IMX_SC_C_PXL_LINK_SLV2_ADDR		9
#define IMX_SC_C_PXL_LINK_MST_VLD		10
#define IMX_SC_C_PXL_LINK_MST1_VLD		11
#define IMX_SC_C_PXL_LINK_MST2_VLD		12
#define IMX_SC_C_SINGLE_MODE			13
#define IMX_SC_C_ID				14
#define IMX_SC_C_PXL_CLK_POLARITY		15
#define IMX_SC_C_LINESTATE			16
#define IMX_SC_C_PCIE_G_RST			17
#define IMX_SC_C_PCIE_BUTTON_RST		18
#define IMX_SC_C_PCIE_PERST			19
#define IMX_SC_C_PHY_RESET			20
#define IMX_SC_C_PXL_LINK_RATE_CORRECTION	21
#define IMX_SC_C_PANIC				22
#define IMX_SC_C_PRIORITY_GROUP			23
#define IMX_SC_C_TXCLK				24
#define IMX_SC_C_CLKDIV				25
#define IMX_SC_C_DISABLE_50			26
#define IMX_SC_C_DISABLE_125			27
#define IMX_SC_C_SEL_125			28
#define IMX_SC_C_MODE				29
#define IMX_SC_C_SYNC_CTRL0			30
#define IMX_SC_C_KACHUNK_CNT			31
#define IMX_SC_C_KACHUNK_SEL			32
#define IMX_SC_C_SYNC_CTRL1			33
#define IMX_SC_C_DPI_RESET			34
#define IMX_SC_C_MIPI_RESET			35
#define IMX_SC_C_DUAL_MODE			36
#define IMX_SC_C_VOLTAGE			37
#define IMX_SC_C_PXL_LINK_SEL			38
#define IMX_SC_C_OFS_SEL			39
#define IMX_SC_C_OFS_AUDIO			40
#define IMX_SC_C_OFS_PERIPH			41
#define IMX_SC_C_OFS_IRQ			42
#define IMX_SC_C_RST0				43
#define IMX_SC_C_RST1				44
#define IMX_SC_C_SEL0				45
#define IMX_SC_C_CALIB0				46
#define IMX_SC_C_CALIB1				47
#define IMX_SC_C_CALIB2				48
#define IMX_SC_C_IPG_DEBUG			49
#define IMX_SC_C_IPG_DOZE			50
#define IMX_SC_C_IPG_WAIT			51
#define IMX_SC_C_IPG_STOP			52
#define IMX_SC_C_IPG_STOP_MODE			53
#define IMX_SC_C_IPG_STOP_ACK			54
#define IMX_SC_C_SYNC_CTRL			55
#define IMX_SC_C_OFS_AUDIO_ALT			56
#define IMX_SC_C_DSP_BYP			57
#define IMX_SC_C_CLK_GEN_EN			58
#define IMX_SC_C_INTF_SEL			59
#define IMX_SC_C_RXC_DLY			60
#define IMX_SC_C_TIMER_SEL			61
#define IMX_SC_C_LAST				62

#endif /* __DT_BINDINGS_RSCRC_IMX_H */
+0 −1
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@
#define _SC_SCI_H

#include <linux/firmware/imx/ipc.h>
#include <linux/firmware/imx/types.h>

#include <linux/firmware/imx/svc/misc.h>
#include <linux/firmware/imx/svc/pm.h>
Loading