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:
koenz
2020-12-18 10:58:13 +08:00
committed by Laxman Dewangan
parent d711403132
commit 7af9118d0a
4 changed files with 125 additions and 27 deletions

View File

@@ -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);

View File

@@ -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,

View File

@@ -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));
}

View File

@@ -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_ */