psc: Add support for mutex mailbox

This change adds support for mailbox with mutex.

In OESP/SB, GP mailboxes are used. Since they are mailbox with mutex,
the driver needs to acquire mutex before using it.

Jira SEC-15577

Signed-off-by: Jason Li (SW-TEGRA) <jasl@nvidia.com>
Change-Id: I8bc95402b1a4fc7227058aded1d417cfa3e5fae6
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261139
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: David Pu <dpu@nvidia.com>
This commit is contained in:
Jason Li
2024-12-17 08:50:12 +00:00
committed by Jon Hunter
parent 00ab7abbb6
commit 1440655254
3 changed files with 109 additions and 28 deletions

View File

@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020-2024, NVIDIA Corporation. All rights reserved. // SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mailbox_client.h> #include <linux/mailbox_client.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/fs.h> #include <linux/fs.h>
@@ -19,6 +18,12 @@
#define EXT_CFG_SIDCONFIG 0x4 #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_READY 1
#define RX_IDLE 0 #define RX_IDLE 0
@@ -73,6 +78,12 @@ enum {
PSC_NUM 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 psc_debug_dev debug_devs[PSC_NUM];
static struct dentry *debugfs[PSC_NUM]; static struct dentry *debugfs[PSC_NUM];
@@ -109,6 +120,56 @@ setup_extcfg(struct platform_device *pdev)
return 0; 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) 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; 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); chan = psc_mbox_request_channel0(dbg->mbox, &dbg->cl);
if (IS_ERR(chan) && (PTR_ERR(chan) != -EPROBE_DEFER)) { if (IS_ERR(chan) && (PTR_ERR(chan) != -EPROBE_DEFER)) {
dev_err(&pdev->dev, "failed to get channel, err %lx\n", 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) static int psc_debug_release(struct inode *inode, struct file *file)
{ {
struct psc_debug_dev *dbg = file->private_data; struct psc_debug_dev *dbg = file->private_data;
struct platform_device *pdev = dbg->pdev;
int ret = 0;
mutex_lock(&dbg->lock); mutex_lock(&dbg->lock);
mbox_free_channel(dbg->chan); 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; file->private_data = NULL;
return_unlock:
mutex_unlock(&dbg->lock); mutex_unlock(&dbg->lock);
return 0; return ret;
} }
static ssize_t psc_debug_read(struct file *file, char __user *buffer, static ssize_t psc_debug_read(struct file *file, char __user *buffer,

View File

@@ -1,7 +1,30 @@
// SPDX-License-Identifier: GPL-2.0 /* SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * 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 <linux/platform_device.h>
#include <linux/mailbox_controller.h>
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) #if defined(CONFIG_DEBUG_FS)
int psc_debugfs_create(struct platform_device *pdev, struct mbox_controller *mbox); 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 readl0(addr) readl((addr))
#define writel0(value, addr) writel((value), (addr)) #define writel0(value, addr) writel((value), (addr))
#endif #endif
#endif

View File

@@ -6,10 +6,8 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h> #include <linux/mailbox_client.h>
/* from drivers/mailbox/mailbox.h */ /* from drivers/mailbox/mailbox.h */
@@ -18,7 +16,6 @@
#include "tegra23x_psc.h" #include "tegra23x_psc.h"
#define MBOX_NUM 8
#define MBOX_REG_OFFSET 0x10000 #define MBOX_REG_OFFSET 0x10000
/* 16 32-bit registers for MBOX_CHAN_IN/OUT */ /* 16 32-bit registers for MBOX_CHAN_IN/OUT */
#define MBOX_MSG_SIZE 16 #define MBOX_MSG_SIZE 16
@@ -37,23 +34,6 @@
#define MBOX_CHAN_TX 0x800 #define MBOX_CHAN_TX 0x800
#define MBOX_CHAN_RX 0x1000 #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 #ifdef PSC_HAVE_NUMA
struct io_data { struct io_data {