mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
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:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user