diff --git a/drivers/platform/tegra/psc/psc_debug.c b/drivers/platform/tegra/psc/psc_debug.c index 28d50000..d7a55984 100644 --- a/drivers/platform/tegra/psc/psc_debug.c +++ b/drivers/platform/tegra/psc/psc_debug.c @@ -1,9 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2020-2024, NVIDIA Corporation. All rights reserved. +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include #include -#include #include #include #include @@ -18,7 +17,13 @@ #define EXT_CFG_SIDTABLE 0x0 #define EXT_CFG_SIDCONFIG 0x4 -#define MBOX_MSG_LEN 64 +#define MBOX_MSG_LEN 64 +#define MBOX_CHAN_AP1_MUTEX 0xc +#define MBOX_MUTEX_ACQUIRE BIT(0) +#define MBOX_MUTEX_RELEASE BIT(4) +#define MBOX_MUTEX_STATE BIT(16) +#define MBOX_MUTEX_STATE_ACQUIRED BIT(16) +#define MBOX_MUTEX_STATE_RELEASED 0x0 #define RX_READY 1 #define RX_IDLE 0 @@ -73,6 +78,12 @@ enum { PSC_NUM }; +enum mbox_mutex_cmd { + MUTEX_CMD_ACQUIRE = 0, + MUTEX_CMD_RELEASE, + MUTEX_CMD_NUM +}; + static struct psc_debug_dev debug_devs[PSC_NUM]; static struct dentry *debugfs[PSC_NUM]; @@ -109,6 +120,56 @@ setup_extcfg(struct platform_device *pdev) return 0; } +static int psc_mbox_setup_mutex_channel0(struct mbox_controller *mbox, + struct mbox_client *cl, + enum mbox_mutex_cmd cmd) +{ + struct device *dev = cl->dev; + struct mbox_chan *chan = &mbox->chans[0]; + struct mbox_vm_chan *vm_chan; + u32 mutex_required; + u32 value; + u32 expected_state; + + if (!dev) { + pr_err("%s: device is NULL\n", __func__); + return -ENODEV; + } + + if (IS_ERR(chan)) { + dev_err(dev, "%s: channel [0] has an error\n", __func__); + return PTR_ERR(chan); + } + + if (cmd >= MUTEX_CMD_NUM) + return -EINVAL; + + /* Skip if nvidia,mailbox-mutex is not defined */ + if (device_property_read_u32(dev, NV(mailbox-mutex), &mutex_required) != 0) + return 0; + + /* Skip if mutex is not required for this mailbox */ + if (mutex_required != 1) + return 0; + + if (cmd == MUTEX_CMD_ACQUIRE) { + value = MBOX_MUTEX_ACQUIRE; + expected_state = MBOX_MUTEX_STATE_ACQUIRED; + } else if (cmd == MUTEX_CMD_RELEASE) { + value = MBOX_MUTEX_RELEASE; + expected_state = MBOX_MUTEX_STATE_RELEASED; + } + + vm_chan = chan->con_priv; + writel0(value, vm_chan->base + MBOX_CHAN_AP1_MUTEX); + + /* Check if mutex is acquired/released successfully */ + value = readl0(vm_chan->base + MBOX_CHAN_AP1_MUTEX); + if ((value & MBOX_MUTEX_STATE) != expected_state) + return -EBUSY; + + return 0; +} static int psc_debug_open(struct inode *inode, struct file *file) { @@ -127,6 +188,12 @@ static int psc_debug_open(struct inode *inode, struct file *file) file->private_data = dbg; + ret = psc_mbox_setup_mutex_channel0(dbg->mbox, &dbg->cl, MUTEX_CMD_ACQUIRE); + if (ret != 0) { + dev_err(&pdev->dev, "failed to acquire mutex, err %d\n", ret); + goto return_unlock; + } + chan = psc_mbox_request_channel0(dbg->mbox, &dbg->cl); if (IS_ERR(chan) && (PTR_ERR(chan) != -EPROBE_DEFER)) { dev_err(&pdev->dev, "failed to get channel, err %lx\n", @@ -148,15 +215,24 @@ return_unlock: static int psc_debug_release(struct inode *inode, struct file *file) { struct psc_debug_dev *dbg = file->private_data; + struct platform_device *pdev = dbg->pdev; + int ret = 0; mutex_lock(&dbg->lock); mbox_free_channel(dbg->chan); + ret = psc_mbox_setup_mutex_channel0(dbg->mbox, &dbg->cl, MUTEX_CMD_RELEASE); + if (ret != 0) { + dev_err(&pdev->dev, "failed to release mutex, err %d\n", ret); + goto return_unlock; + } + file->private_data = NULL; +return_unlock: mutex_unlock(&dbg->lock); - return 0; + return ret; } static ssize_t psc_debug_read(struct file *file, char __user *buffer, diff --git a/drivers/platform/tegra/psc/tegra23x_psc.h b/drivers/platform/tegra/psc/tegra23x_psc.h index cacc9b05..a5a34374 100644 --- a/drivers/platform/tegra/psc/tegra23x_psc.h +++ b/drivers/platform/tegra/psc/tegra23x_psc.h @@ -1,7 +1,30 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* SPDX-License-Identifier: GPL-2.0-only + * SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ -struct mbox_controller; +#ifndef TEGRA23X_PSC_H +#define TEGRA23X_PSC_H + +#define MBOX_NUM 8 + +#include +#include + +struct psc_mbox; + +struct mbox_vm_chan { + unsigned int irq; + void __iomem *base; + struct psc_mbox *parent; +}; + +struct psc_mbox { + struct device *dev; + void __iomem *vm_chan_base; + struct mbox_chan chan[MBOX_NUM]; + struct mbox_controller mbox; + struct mbox_vm_chan vm_chan[MBOX_NUM]; +}; #if defined(CONFIG_DEBUG_FS) int psc_debugfs_create(struct platform_device *pdev, struct mbox_controller *mbox); @@ -28,3 +51,5 @@ void writel0(u32 value, void __iomem *addr); #define readl0(addr) readl((addr)) #define writel0(value, addr) writel((value), (addr)) #endif + +#endif diff --git a/drivers/platform/tegra/psc/tegra23x_psc_mailbox.c b/drivers/platform/tegra/psc/tegra23x_psc_mailbox.c index c01a67dd..bfaa4df8 100644 --- a/drivers/platform/tegra/psc/tegra23x_psc_mailbox.c +++ b/drivers/platform/tegra/psc/tegra23x_psc_mailbox.c @@ -6,10 +6,8 @@ #include #include #include -#include #include #include -#include #include /* from drivers/mailbox/mailbox.h */ @@ -18,7 +16,6 @@ #include "tegra23x_psc.h" -#define MBOX_NUM 8 #define MBOX_REG_OFFSET 0x10000 /* 16 32-bit registers for MBOX_CHAN_IN/OUT */ #define MBOX_MSG_SIZE 16 @@ -37,23 +34,6 @@ #define MBOX_CHAN_TX 0x800 #define MBOX_CHAN_RX 0x1000 -struct psc_mbox; - -struct mbox_vm_chan { - unsigned int irq; - void __iomem *base; - struct psc_mbox *parent; -}; - -struct psc_mbox { - struct device *dev; - void __iomem *vm_chan_base; - struct mbox_chan chan[MBOX_NUM]; - struct mbox_controller mbox; - struct mbox_vm_chan vm_chan[MBOX_NUM]; -}; - - #ifdef PSC_HAVE_NUMA struct io_data {