mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 01:31:30 +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.
|
* 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
|
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License,
|
* 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
|
#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 */
|
/* clock */
|
||||||
int esc_mods_get_clock_handle(struct mods_client *client,
|
int esc_mods_get_clock_handle(struct mods_client *client,
|
||||||
struct MODS_GET_CLOCK_HANDLE *p);
|
struct MODS_GET_CLOCK_HANDLE *p);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* mods_krnl.c - This file is part of NVIDIA MODS kernel driver.
|
* 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
|
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License,
|
* 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 int mods_krnl_mmap(struct file *, struct vm_area_struct *);
|
||||||
static long mods_krnl_ioctl(struct file *, unsigned int, unsigned long);
|
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 */
|
/* character driver entry points */
|
||||||
static const struct file_operations mods_fops = {
|
static const struct file_operations mods_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
@@ -120,6 +116,10 @@ static int mods_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||||||
return 0;
|
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 = {
|
struct pci_driver mods_pci_driver = {
|
||||||
.name = DEVICE_NAME,
|
.name = DEVICE_NAME,
|
||||||
.id_table = mods_pci_table,
|
.id_table = mods_pci_table,
|
||||||
@@ -150,27 +150,14 @@ static u32 access_token = MODS_ACCESS_TOKEN_NONE;
|
|||||||
static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||||
{
|
{
|
||||||
int totalvfs;
|
int totalvfs;
|
||||||
struct en_dev_entry *dpriv;
|
int err = 0;
|
||||||
|
|
||||||
LOG_ENT();
|
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);
|
totalvfs = pci_sriov_get_totalvfs(dev);
|
||||||
|
|
||||||
if (numvfs > 0) {
|
if (numvfs > 0) {
|
||||||
int err = pci_enable_sriov(dev, numvfs);
|
err = pci_enable_sriov(dev, numvfs);
|
||||||
|
|
||||||
if (unlikely(err)) {
|
if (unlikely(err)) {
|
||||||
mods_error_printk(
|
mods_error_printk(
|
||||||
@@ -185,8 +172,6 @@ static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
|||||||
err);
|
err);
|
||||||
numvfs = err;
|
numvfs = err;
|
||||||
} else {
|
} else {
|
||||||
dpriv->num_vfs = numvfs;
|
|
||||||
|
|
||||||
mods_info_printk(
|
mods_info_printk(
|
||||||
"enabled sriov on dev %04x:%02x:%02x.%x %s numvfs=%d (totalvfs=%d)\n",
|
"enabled sriov on dev %04x:%02x:%02x.%x %s numvfs=%d (totalvfs=%d)\n",
|
||||||
pci_domain_nr(dev->bus),
|
pci_domain_nr(dev->bus),
|
||||||
@@ -200,8 +185,8 @@ static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
pci_disable_sriov(dev);
|
pci_disable_sriov(dev);
|
||||||
|
|
||||||
numvfs = 0;
|
numvfs = 0;
|
||||||
dpriv->num_vfs = 0;
|
|
||||||
|
|
||||||
mods_info_printk(
|
mods_info_printk(
|
||||||
"disabled sriov on dev %04x:%02x:%02x.%x %s (totalvfs=%d)\n",
|
"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);
|
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();
|
LOG_EXT();
|
||||||
return numvfs;
|
return numvfs;
|
||||||
}
|
}
|
||||||
@@ -2356,6 +2349,17 @@ static long mods_krnl_ioctl(struct file *fp,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_ARCH_TEGRA)
|
#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:
|
case MODS_ESC_FLUSH_CPU_CACHE_RANGE:
|
||||||
MODS_IOCTL_NORETVAL(MODS_ESC_FLUSH_CPU_CACHE_RANGE,
|
MODS_IOCTL_NORETVAL(MODS_ESC_FLUSH_CPU_CACHE_RANGE,
|
||||||
esc_mods_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.
|
* 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
|
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License,
|
* modify it under the terms of the GNU General Public License,
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/tegra_prod.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_REG_INFO_ENTRY 400
|
||||||
#define MAX_IO_MAP_ENTRY 200
|
#define MAX_IO_MAP_ENTRY 200
|
||||||
@@ -636,3 +638,68 @@ int esc_mods_tegra_prod_set_prod_exact(
|
|||||||
return ret;
|
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.
|
* 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
|
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License,
|
* 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;
|
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 */
|
/* Used by legacy MODS_ESC_FIND_PCI_DEVICE ioctl */
|
||||||
struct MODS_FIND_PCI_DEVICE {
|
struct MODS_FIND_PCI_DEVICE {
|
||||||
/* IN */
|
/* 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_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_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_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_ */
|
#endif /* _UAPI_MODS_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user