mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
mods-kernel-driver: BPMP Uphy driver support
JIRA: TM-127 - Adding ioctl commands for setting PCIE state and initialize PCIE EP PLL; - Sync some code from perforce; DVS: http://ausdvs.nvidia.com/Build_Results?virtualId=1000859480 Signed-off-by: Koen Zhao <koenz@nvidia.com> Change-Id: I4f9024f5037060a7c78f337148b202a078cbc4ba Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2461698 Reviewed-by: svcacv <svcacv@nvidia.com> Reviewed-by: Chris Dragan <kdragan@nvidia.com> Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* mods_internal.h - This file is part of NVIDIA MODS kernel driver.
|
||||
*
|
||||
* Copyright (c) 2008-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2008-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License,
|
||||
@@ -579,6 +579,12 @@ int esc_mods_query_irq_3(struct mods_client *client,
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
|
||||
/* bpmp uphy */
|
||||
int esc_mods_bpmp_set_pcie_state(struct mods_client *client,
|
||||
struct MODS_SET_PCIE_STATE *p);
|
||||
int esc_mods_bpmp_init_pcie_ep_pll(struct mods_client *client,
|
||||
struct MODS_INIT_PCIE_EP_PLL *p);
|
||||
|
||||
/* clock */
|
||||
int esc_mods_get_clock_handle(struct mods_client *client,
|
||||
struct MODS_GET_CLOCK_HANDLE *p);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* mods_krnl.c - This file is part of NVIDIA MODS kernel driver.
|
||||
*
|
||||
* Copyright (c) 2008-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2008-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License,
|
||||
@@ -50,10 +50,6 @@ static unsigned int mods_krnl_poll(struct file *, poll_table *);
|
||||
static int mods_krnl_mmap(struct file *, struct vm_area_struct *);
|
||||
static long mods_krnl_ioctl(struct file *, unsigned int, unsigned long);
|
||||
|
||||
#if defined(CONFIG_PCI) && defined(MODS_HAS_SRIOV)
|
||||
static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs);
|
||||
#endif
|
||||
|
||||
/* character driver entry points */
|
||||
static const struct file_operations mods_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -120,6 +116,10 @@ static int mods_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PCI) && defined(MODS_HAS_SRIOV)
|
||||
static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs);
|
||||
#endif
|
||||
|
||||
struct pci_driver mods_pci_driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.id_table = mods_pci_table,
|
||||
@@ -149,28 +149,15 @@ static u32 access_token = MODS_ACCESS_TOKEN_NONE;
|
||||
#if defined(CONFIG_PCI) && defined(MODS_HAS_SRIOV)
|
||||
static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
{
|
||||
int totalvfs;
|
||||
struct en_dev_entry *dpriv;
|
||||
int totalvfs;
|
||||
int err = 0;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
dpriv = pci_get_drvdata(dev);
|
||||
if (!dpriv) {
|
||||
mods_error_printk(
|
||||
"failed to enable sriov, dev %04x:%02x:%02x.%x was not enabled\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
|
||||
LOG_EXT();
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
totalvfs = pci_sriov_get_totalvfs(dev);
|
||||
|
||||
if (numvfs > 0) {
|
||||
int err = pci_enable_sriov(dev, numvfs);
|
||||
err = pci_enable_sriov(dev, numvfs);
|
||||
|
||||
if (unlikely(err)) {
|
||||
mods_error_printk(
|
||||
@@ -185,8 +172,6 @@ static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
err);
|
||||
numvfs = err;
|
||||
} else {
|
||||
dpriv->num_vfs = numvfs;
|
||||
|
||||
mods_info_printk(
|
||||
"enabled sriov on dev %04x:%02x:%02x.%x %s numvfs=%d (totalvfs=%d)\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
@@ -200,8 +185,8 @@ static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
|
||||
} else {
|
||||
pci_disable_sriov(dev);
|
||||
|
||||
numvfs = 0;
|
||||
dpriv->num_vfs = 0;
|
||||
|
||||
mods_info_printk(
|
||||
"disabled sriov on dev %04x:%02x:%02x.%x %s (totalvfs=%d)\n",
|
||||
@@ -213,6 +198,14 @@ static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
totalvfs);
|
||||
}
|
||||
|
||||
/* If this function has been invoked via an ioctl, remember numvfs */
|
||||
if (!err) {
|
||||
struct en_dev_entry *dpriv = pci_get_drvdata(dev);
|
||||
|
||||
if (dpriv)
|
||||
dpriv->num_vfs = numvfs;
|
||||
}
|
||||
|
||||
LOG_EXT();
|
||||
return numvfs;
|
||||
}
|
||||
@@ -2356,6 +2349,17 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_TEGRA)
|
||||
case MODS_ESC_BPMP_SET_PCIE_STATE:
|
||||
MODS_IOCTL(MODS_ESC_BPMP_SET_PCIE_STATE,
|
||||
esc_mods_bpmp_set_pcie_state,
|
||||
MODS_SET_PCIE_STATE);
|
||||
break;
|
||||
|
||||
case MODS_ESC_BPMP_INIT_PCIE_EP_PLL:
|
||||
MODS_IOCTL(MODS_ESC_BPMP_INIT_PCIE_EP_PLL,
|
||||
esc_mods_bpmp_init_pcie_ep_pll,
|
||||
MODS_INIT_PCIE_EP_PLL);
|
||||
break;
|
||||
case MODS_ESC_FLUSH_CPU_CACHE_RANGE:
|
||||
MODS_IOCTL_NORETVAL(MODS_ESC_FLUSH_CPU_CACHE_RANGE,
|
||||
esc_mods_flush_cpu_cache_range,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* mods_tegraprod.c - This file is part of NVIDIA MODS kernel driver.
|
||||
*
|
||||
* Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License,
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/tegra_prod.h>
|
||||
#include <soc/tegra/bpmp_abi.h>
|
||||
#include <soc/tegra/tegra_bpmp.h>
|
||||
|
||||
#define MAX_REG_INFO_ENTRY 400
|
||||
#define MAX_IO_MAP_ENTRY 200
|
||||
@@ -636,3 +638,68 @@ int esc_mods_tegra_prod_set_prod_exact(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bpmp_send_uphy_message_atomic(
|
||||
struct mrq_uphy_request *req, int size,
|
||||
struct mrq_uphy_response *reply,
|
||||
int reply_size
|
||||
)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
local_irq_save(flags);
|
||||
err = tegra_bpmp_send_receive_atomic(MRQ_UPHY, req, size, reply,
|
||||
reply_size);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bpmp_send_uphy_message(
|
||||
struct mrq_uphy_request *req, int size,
|
||||
struct mrq_uphy_response *reply,
|
||||
int reply_size
|
||||
)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = tegra_bpmp_send_receive(MRQ_UPHY, req, size, reply, reply_size);
|
||||
if (err != -EAGAIN)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* in case the mail systems worker threads haven't been started yet,
|
||||
* use the atomic send/receive interface. This happens because the
|
||||
* clocks are initialized before the IPC mechanism.
|
||||
*/
|
||||
return bpmp_send_uphy_message_atomic(req, size, reply, reply_size);
|
||||
}
|
||||
|
||||
int esc_mods_bpmp_set_pcie_state(
|
||||
struct mods_client *client,
|
||||
struct MODS_SET_PCIE_STATE *p
|
||||
)
|
||||
{
|
||||
struct mrq_uphy_request req;
|
||||
struct mrq_uphy_response resp;
|
||||
|
||||
req.cmd = CMD_UPHY_PCIE_CONTROLLER_STATE;
|
||||
req.controller_state.pcie_controller = p->controller;
|
||||
req.controller_state.enable = p->enable;
|
||||
|
||||
return bpmp_send_uphy_message(&req, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int esc_mods_bpmp_init_pcie_ep_pll(
|
||||
struct mods_client *client,
|
||||
struct MODS_INIT_PCIE_EP_PLL *p
|
||||
)
|
||||
{
|
||||
struct mrq_uphy_request req;
|
||||
struct mrq_uphy_response resp;
|
||||
|
||||
req.cmd = CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT;
|
||||
req.ep_ctrlr_pll_init.ep_controller = p->ep_id;
|
||||
|
||||
return bpmp_send_uphy_message(&req, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* mods.h - This file is part of NVIDIA MODS kernel driver.
|
||||
*
|
||||
* Copyright (c) 2008-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2008-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License,
|
||||
@@ -418,6 +418,25 @@ struct MODS_FIND_PCI_DEVICE_2 {
|
||||
struct mods_pci_dev_2 pci_device;
|
||||
};
|
||||
|
||||
/* Used by MODS_ESC_BPMP_SET_PCIE_STATE ioctl.
|
||||
*
|
||||
* Set PCIE state through BPMP Uphy driver
|
||||
*/
|
||||
struct MODS_SET_PCIE_STATE {
|
||||
/* IN */
|
||||
__u32 controller;
|
||||
__u32 enable;
|
||||
};
|
||||
|
||||
/* Used by MODS_ESC_BPMP_INIT_PCIE_EP_PLL ioctl.
|
||||
*
|
||||
* Initialize PCIE EP PLL through BPMP Uphy driver
|
||||
*/
|
||||
struct MODS_INIT_PCIE_EP_PLL {
|
||||
/* IN */
|
||||
__u32 ep_id;
|
||||
};
|
||||
|
||||
/* Used by legacy MODS_ESC_FIND_PCI_DEVICE ioctl */
|
||||
struct MODS_FIND_PCI_DEVICE {
|
||||
/* IN */
|
||||
@@ -1958,5 +1977,7 @@ struct MODS_IOMMU_DMA_MAP_MEMORY {
|
||||
#define MODS_ESC_SYSCTL_WRITE_INT MODSIO(W, 133, MODS_SYSCTL_INT)
|
||||
#define MODS_ESC_PCI_RESET_FUNCTION MODSIO(W, 134, mods_pci_dev_2)
|
||||
#define MODS_ESC_MODS_GET_DRIVER_STATS MODSIO(R, 135, MODS_GET_DRIVER_STATS)
|
||||
#define MODS_ESC_BPMP_SET_PCIE_STATE MODSIO(W, 136, MODS_SET_PCIE_STATE)
|
||||
#define MODS_ESC_BPMP_INIT_PCIE_EP_PLL MODSIO(W, 137, MODS_INIT_PCIE_EP_PLL)
|
||||
|
||||
#endif /* _UAPI_MODS_H_ */
|
||||
|
||||
Reference in New Issue
Block a user