mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
msm: pcie: add snapshot of PCIe root complex bus driver
This is a snapshot of MSM PCIe root complex as of msm-4.19
commit 6e2242593d4a ("drm/msm/dp: check for invalid seqno before
clearing a txmsg slot").
Changes made:
- remove or switch to sysfs for all module params
- move from MSM bus to ICC framework
- replace all snprintf with scnprintf
- update debugfs remove
- update license for msm_pcie.h
- misc syntax improvements
Change-Id: I310fdfd136346f74c20806bd5dcdbc74c7d894a3
Signed-off-by: Tony Truong <truong@codeaurora.org>
This commit is contained in:
parent
635b627365
commit
eb3beebb57
5 changed files with 8014 additions and 0 deletions
|
|
@ -288,5 +288,30 @@ config PCI_HYPERV_INTERFACE
|
|||
The Hyper-V PCI Interface is a helper driver allows other drivers to
|
||||
have a common interface with the Hyper-V PCI frontend driver.
|
||||
|
||||
config PCI_MSM
|
||||
tristate "MSM PCIe Controller driver"
|
||||
depends on ARCH_QCOM && PCI
|
||||
select PCI_DOMAINS
|
||||
select PCI_DOMAINS_GENERIC
|
||||
select PCI_MSI
|
||||
select CRC8
|
||||
help
|
||||
Enables the PCIe functionality by configuring PCIe core on
|
||||
MSM chipset and by enabling the ARM PCI framework extension.
|
||||
The PCIe core is essential for communication between the host
|
||||
and an endpoint.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PCI_MSM_MSI
|
||||
tristate "MSM PCIe MSI support"
|
||||
depends on PCI_MSM
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
help
|
||||
Say Y here if you want to enable MSI support for PCIe
|
||||
controller and its devices. This controller offers
|
||||
message signaled interrupts (MSI) allocation, routing,
|
||||
masking, and affinity assigning for PCIe devices.
|
||||
|
||||
source "drivers/pci/controller/dwc/Kconfig"
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
|
|||
obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
|
||||
obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
|
||||
obj-$(CONFIG_VMD) += vmd.o
|
||||
obj-$(CONFIG_PCI_MSM) += pci-msm.o
|
||||
obj-$(CONFIG_PCI_MSM_MSI) += pci-msm-msi.o
|
||||
# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
|
||||
obj-y += dwc/
|
||||
|
||||
|
|
|
|||
430
drivers/pci/controller/pci-msm-msi.c
Normal file
430
drivers/pci/controller/pci-msm-msi.c
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/ipc_logging.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
struct msm_msi_irq {
|
||||
unsigned int hwirq; /* MSI controller hwirq */
|
||||
unsigned int virq; /* MSI controller virq */
|
||||
};
|
||||
|
||||
struct msm_msi {
|
||||
struct list_head clients;
|
||||
struct device *dev;
|
||||
struct device_node *of_node;
|
||||
int nr_irqs;
|
||||
struct msm_msi_irq *irqs;
|
||||
unsigned long *bitmap; /* tracks used/unused MSI */
|
||||
struct mutex mutex; /* mutex for modifying MSI client list and bitmap */
|
||||
struct irq_domain *inner_domain; /* parent domain; gen irq related */
|
||||
struct irq_domain *msi_domain; /* child domain; pci related */
|
||||
phys_addr_t msi_addr;
|
||||
};
|
||||
|
||||
/* structure for each client of MSI controller */
|
||||
struct msm_msi_client {
|
||||
struct list_head node;
|
||||
struct msm_msi *msi;
|
||||
struct device *dev; /* client's dev of pci_dev */
|
||||
u32 nr_irqs; /* nr_irqs allocated for client */
|
||||
dma_addr_t msi_addr;
|
||||
};
|
||||
|
||||
static void msm_msi_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct msm_msi *msi;
|
||||
unsigned int virq;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
msi = irq_desc_get_handler_data(desc);
|
||||
virq = irq_find_mapping(msi->inner_domain, irq_desc_get_irq(desc));
|
||||
|
||||
generic_handle_irq(virq);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static void msm_msi_mask_irq(struct irq_data *data)
|
||||
{
|
||||
struct irq_data *parent_data;
|
||||
|
||||
if (!data->parent_data)
|
||||
return;
|
||||
|
||||
parent_data = irq_get_irq_data(data->parent_data->hwirq);
|
||||
if (!parent_data || !parent_data->chip)
|
||||
return;
|
||||
|
||||
pci_msi_mask_irq(data);
|
||||
parent_data->chip->irq_mask(parent_data);
|
||||
}
|
||||
|
||||
static void msm_msi_unmask_irq(struct irq_data *data)
|
||||
{
|
||||
struct irq_data *parent_data;
|
||||
|
||||
if (!data->parent_data)
|
||||
return;
|
||||
|
||||
parent_data = irq_get_irq_data(data->parent_data->hwirq);
|
||||
if (!parent_data || !parent_data->chip)
|
||||
return;
|
||||
|
||||
parent_data->chip->irq_unmask(parent_data);
|
||||
pci_msi_unmask_irq(data);
|
||||
}
|
||||
|
||||
static struct irq_chip msm_msi_irq_chip = {
|
||||
.name = "msm_pci_msi",
|
||||
.irq_enable = msm_msi_unmask_irq,
|
||||
.irq_disable = msm_msi_mask_irq,
|
||||
.irq_mask = msm_msi_mask_irq,
|
||||
.irq_unmask = msm_msi_unmask_irq,
|
||||
};
|
||||
|
||||
static int msm_msi_domain_prepare(struct irq_domain *domain, struct device *dev,
|
||||
int nvec, msi_alloc_info_t *arg)
|
||||
{
|
||||
struct msm_msi *msi = domain->parent->host_data;
|
||||
struct msm_msi_client *client;
|
||||
|
||||
client = devm_kzalloc(msi->dev, sizeof(*client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
client->msi = msi;
|
||||
client->dev = dev;
|
||||
client->msi_addr = dma_map_resource(client->dev, msi->msi_addr,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE, 0);
|
||||
if (dma_mapping_error(client->dev, client->msi_addr)) {
|
||||
dev_err(msi->dev, "MSI: failed to map msi address\n");
|
||||
client->msi_addr = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&msi->mutex);
|
||||
list_add_tail(&client->node, &msi->clients);
|
||||
mutex_unlock(&msi->mutex);
|
||||
|
||||
/* zero out struct for framework */
|
||||
memset(arg, 0, sizeof(*arg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msm_msi_domain_finish(msi_alloc_info_t *arg, int retval)
|
||||
{
|
||||
struct device *dev = arg->desc->dev;
|
||||
struct irq_domain *domain = dev_get_msi_domain(dev);
|
||||
struct msm_msi *msi = domain->parent->host_data;
|
||||
|
||||
/* if prepare or alloc fails, then clean up */
|
||||
if (retval) {
|
||||
struct msm_msi_client *tmp, *client = NULL;
|
||||
|
||||
mutex_lock(&msi->mutex);
|
||||
list_for_each_entry(tmp, &msi->clients, node) {
|
||||
if (tmp->dev == dev) {
|
||||
client = tmp;
|
||||
list_del(&client->node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&msi->mutex);
|
||||
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
if (client->msi_addr)
|
||||
dma_unmap_resource(client->dev, client->msi_addr,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE, 0);
|
||||
|
||||
devm_kfree(msi->dev, client);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static struct msi_domain_ops msm_msi_domain_ops = {
|
||||
.msi_prepare = msm_msi_domain_prepare,
|
||||
.msi_finish = msm_msi_domain_finish,
|
||||
};
|
||||
|
||||
static struct msi_domain_info msm_msi_domain_info = {
|
||||
.flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
||||
MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
|
||||
.ops = &msm_msi_domain_ops,
|
||||
.chip = &msm_msi_irq_chip,
|
||||
};
|
||||
|
||||
static int msm_msi_irq_set_affinity(struct irq_data *data,
|
||||
const struct cpumask *mask, bool force)
|
||||
{
|
||||
struct irq_data *parent_data = irq_get_irq_data(irqd_to_hwirq(data));
|
||||
|
||||
if (!parent_data)
|
||||
return -ENODEV;
|
||||
|
||||
/* set affinity for MSM MSI HW IRQ */
|
||||
if (parent_data->chip->irq_set_affinity)
|
||||
return parent_data->chip->irq_set_affinity(parent_data,
|
||||
mask, force);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void msm_msi_irq_compose_msi_msg(struct irq_data *data,
|
||||
struct msi_msg *msg)
|
||||
{
|
||||
struct msm_msi_client *client = irq_data_get_irq_chip_data(data);
|
||||
struct irq_data *parent_data = irq_get_irq_data(irqd_to_hwirq(data));
|
||||
|
||||
if (!parent_data)
|
||||
return;
|
||||
|
||||
msg->address_lo = lower_32_bits(client->msi_addr);
|
||||
msg->address_hi = upper_32_bits(client->msi_addr);
|
||||
|
||||
/* GIC HW IRQ */
|
||||
msg->data = irqd_to_hwirq(parent_data);
|
||||
}
|
||||
|
||||
static struct irq_chip msm_msi_bottom_irq_chip = {
|
||||
.name = "msm_msi",
|
||||
.irq_set_affinity = msm_msi_irq_set_affinity,
|
||||
.irq_compose_msi_msg = msm_msi_irq_compose_msi_msg,
|
||||
};
|
||||
|
||||
static int msm_msi_irq_domain_alloc(struct irq_domain *domain,
|
||||
unsigned int virq, unsigned int nr_irqs,
|
||||
void *args)
|
||||
{
|
||||
struct msm_msi *msi = domain->host_data;
|
||||
struct msm_msi_client *tmp, *client = NULL;
|
||||
struct device *dev = ((msi_alloc_info_t *)args)->desc->dev;
|
||||
int i, ret = 0;
|
||||
int pos;
|
||||
|
||||
mutex_lock(&msi->mutex);
|
||||
list_for_each_entry(tmp, &msi->clients, node) {
|
||||
if (tmp->dev == dev) {
|
||||
client = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!client) {
|
||||
dev_err(msi->dev, "MSI: failed to find client dev\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos = bitmap_find_next_zero_area(msi->bitmap, msi->nr_irqs, 0,
|
||||
nr_irqs, 0);
|
||||
if (pos < msi->nr_irqs) {
|
||||
bitmap_set(msi->bitmap, pos, nr_irqs);
|
||||
} else {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
msi->irqs[pos].virq = virq + i;
|
||||
irq_domain_set_info(domain, msi->irqs[pos].virq,
|
||||
msi->irqs[pos].hwirq,
|
||||
&msm_msi_bottom_irq_chip, client,
|
||||
handle_simple_irq, NULL, NULL);
|
||||
client->nr_irqs++;
|
||||
pos++;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&msi->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void msm_msi_irq_domain_free(struct irq_domain *domain,
|
||||
unsigned int virq, unsigned int nr_irqs)
|
||||
{
|
||||
struct irq_data *data = irq_domain_get_irq_data(domain, virq);
|
||||
struct msm_msi_client *client;
|
||||
struct msm_msi *msi;
|
||||
int i;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
client = irq_data_get_irq_chip_data(data);
|
||||
msi = client->msi;
|
||||
|
||||
mutex_lock(&msi->mutex);
|
||||
for (i = 0; i < nr_irqs; i++)
|
||||
if (msi->irqs[i].virq == virq)
|
||||
break;
|
||||
|
||||
bitmap_clear(msi->bitmap, i, nr_irqs);
|
||||
client->nr_irqs -= nr_irqs;
|
||||
|
||||
if (!client->nr_irqs) {
|
||||
dma_unmap_resource(client->dev, client->msi_addr, PAGE_SIZE,
|
||||
DMA_FROM_DEVICE, 0);
|
||||
list_del(&client->node);
|
||||
devm_kfree(msi->dev, client);
|
||||
}
|
||||
|
||||
mutex_unlock(&msi->mutex);
|
||||
|
||||
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops msi_domain_ops = {
|
||||
.alloc = msm_msi_irq_domain_alloc,
|
||||
.free = msm_msi_irq_domain_free,
|
||||
};
|
||||
|
||||
static int msm_msi_alloc_domains(struct msm_msi *msi)
|
||||
{
|
||||
msi->inner_domain = irq_domain_add_linear(NULL, msi->nr_irqs,
|
||||
&msi_domain_ops, msi);
|
||||
if (!msi->inner_domain) {
|
||||
dev_err(msi->dev, "MSI: failed to create IRQ domain\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
msi->msi_domain = pci_msi_create_irq_domain(
|
||||
of_node_to_fwnode(msi->of_node),
|
||||
&msm_msi_domain_info,
|
||||
msi->inner_domain);
|
||||
if (!msi->msi_domain) {
|
||||
dev_err(msi->dev, "MSI: failed to create MSI domain\n");
|
||||
irq_domain_remove(msi->inner_domain);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_msi_init(struct device *dev)
|
||||
{
|
||||
int i, ret;
|
||||
struct msm_msi *msi;
|
||||
struct device_node *of_node;
|
||||
const __be32 *prop_val;
|
||||
|
||||
if (!dev->of_node) {
|
||||
dev_err(dev, "MSI: missing DT node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
of_node = of_parse_phandle(dev->of_node, "msi-parent", 0);
|
||||
if (!of_node) {
|
||||
dev_err(dev, "MSI: no phandle for MSI found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!of_device_is_compatible(of_node, "qcom,pci-msi")) {
|
||||
dev_err(dev, "MSI: no compatible qcom,pci-msi found\n");
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!of_find_property(of_node, "msi-controller", NULL)) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msi = devm_kzalloc(dev, sizeof(*msi), GFP_KERNEL);
|
||||
if (!msi) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msi->dev = dev;
|
||||
msi->of_node = of_node;
|
||||
mutex_init(&msi->mutex);
|
||||
INIT_LIST_HEAD(&msi->clients);
|
||||
|
||||
prop_val = of_get_address(msi->of_node, 0, NULL, NULL);
|
||||
if (!prop_val) {
|
||||
dev_err(msi->dev, "MSI: missing 'reg' devicetree\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msi->msi_addr = be32_to_cpup(prop_val);
|
||||
if (!msi->msi_addr) {
|
||||
dev_err(msi->dev, "MSI: failed to get MSI address\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msi->nr_irqs = of_irq_count(msi->of_node);
|
||||
if (!msi->nr_irqs) {
|
||||
dev_err(msi->dev, "MSI: found no MSI interrupts\n");
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msi->irqs = devm_kcalloc(msi->dev, msi->nr_irqs,
|
||||
sizeof(*msi->irqs), GFP_KERNEL);
|
||||
if (!msi->irqs) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msi->bitmap = devm_kcalloc(msi->dev, BITS_TO_LONGS(msi->nr_irqs),
|
||||
sizeof(*msi->bitmap), GFP_KERNEL);
|
||||
if (!msi->bitmap) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = msm_msi_alloc_domains(msi);
|
||||
if (ret) {
|
||||
dev_err(msi->dev, "MSI: failed to allocate MSI domains\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < msi->nr_irqs; i++) {
|
||||
unsigned int irq = irq_of_parse_and_map(msi->of_node, i);
|
||||
|
||||
if (!irq) {
|
||||
dev_err(msi->dev,
|
||||
"MSI: failed to parse/map interrupt\n");
|
||||
ret = -ENODEV;
|
||||
goto free_irqs;
|
||||
}
|
||||
|
||||
msi->irqs[i].hwirq = irq;
|
||||
irq_set_chained_handler_and_data(msi->irqs[i].hwirq,
|
||||
msm_msi_handler, msi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_irqs:
|
||||
for (--i; i >= 0; i--) {
|
||||
irq_set_chained_handler_and_data(msi->irqs[i].hwirq,
|
||||
NULL, NULL);
|
||||
irq_dispose_mapping(msi->irqs[i].hwirq);
|
||||
}
|
||||
|
||||
irq_domain_remove(msi->msi_domain);
|
||||
irq_domain_remove(msi->inner_domain);
|
||||
err:
|
||||
of_node_put(of_node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_msi_init);
|
||||
7310
drivers/pci/controller/pci-msm.c
Normal file
7310
drivers/pci/controller/pci-msm.c
Normal file
File diff suppressed because it is too large
Load diff
247
include/linux/msm_pcie.h
Normal file
247
include/linux/msm_pcie.h
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#ifndef __MSM_PCIE_H
|
||||
#define __MSM_PCIE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
enum msm_pcie_config {
|
||||
MSM_PCIE_CONFIG_INVALID = 0,
|
||||
MSM_PCIE_CONFIG_NO_CFG_RESTORE = 0x1,
|
||||
MSM_PCIE_CONFIG_LINKDOWN = 0x2,
|
||||
MSM_PCIE_CONFIG_NO_RECOVERY = 0x4,
|
||||
};
|
||||
|
||||
enum msm_pcie_pm_opt {
|
||||
MSM_PCIE_DRV_SUSPEND,
|
||||
MSM_PCIE_SUSPEND,
|
||||
MSM_PCIE_RESUME,
|
||||
MSM_PCIE_DISABLE_PC,
|
||||
MSM_PCIE_ENABLE_PC,
|
||||
};
|
||||
|
||||
enum msm_pcie_event {
|
||||
MSM_PCIE_EVENT_INVALID = 0,
|
||||
MSM_PCIE_EVENT_LINKDOWN = 0x1,
|
||||
MSM_PCIE_EVENT_LINKUP = 0x2,
|
||||
MSM_PCIE_EVENT_WAKEUP = 0x4,
|
||||
MSM_PCIE_EVENT_L1SS_TIMEOUT = BIT(3),
|
||||
MSM_PCIE_EVENT_DRV_CONNECT = BIT(4),
|
||||
MSM_PCIE_EVENT_DRV_DISCONNECT = BIT(5),
|
||||
};
|
||||
|
||||
enum msm_pcie_trigger {
|
||||
MSM_PCIE_TRIGGER_CALLBACK,
|
||||
MSM_PCIE_TRIGGER_COMPLETION,
|
||||
};
|
||||
|
||||
struct msm_pcie_notify {
|
||||
enum msm_pcie_event event;
|
||||
void *user;
|
||||
void *data;
|
||||
u32 options;
|
||||
};
|
||||
|
||||
struct msm_pcie_register_event {
|
||||
u32 events;
|
||||
void *user;
|
||||
enum msm_pcie_trigger mode;
|
||||
void (*callback)(struct msm_pcie_notify *notify);
|
||||
struct msm_pcie_notify notify;
|
||||
struct completion *completion;
|
||||
u32 options;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM_MSI)
|
||||
int msm_msi_init(struct device *dev);
|
||||
#else
|
||||
static inline int msm_msi_init(struct device *dev)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
|
||||
/**
|
||||
* msm_pcie_set_link_bandwidth - updates the number of lanes and speed of PCIe
|
||||
* link.
|
||||
* @pci_dev: client's pci device structure
|
||||
* @target_link_speed: gen speed
|
||||
* @target_link_width: number of lanes
|
||||
*
|
||||
* This function gives PCIe clients the control to update the number of lanes
|
||||
* and gen speed of the link.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
|
||||
u16 target_link_width);
|
||||
|
||||
/**
|
||||
* msm_pcie_l1ss_timeout_disable - disable L1ss timeout feature
|
||||
* @pci_dev: client's pci device structure
|
||||
*
|
||||
* This function gives PCIe clients the control to disable L1ss timeout
|
||||
* feature.
|
||||
*/
|
||||
void msm_pcie_l1ss_timeout_disable(struct pci_dev *pci_dev);
|
||||
|
||||
/**
|
||||
* msm_pcie_l1ss_timeout_enable - enable L1ss timeout feature
|
||||
* @pci_dev: client's pci device structure
|
||||
*
|
||||
* This function gives PCIe clients the control to enable L1ss timeout
|
||||
* feature.
|
||||
*/
|
||||
void msm_pcie_l1ss_timeout_enable(struct pci_dev *pci_dev);
|
||||
|
||||
/**
|
||||
* msm_pcie_pm_control - control the power state of a PCIe link.
|
||||
* @pm_opt: power management operation
|
||||
* @busnr: bus number of PCIe endpoint
|
||||
* @user: handle of the caller
|
||||
* @data: private data from the caller
|
||||
* @options: options for pm control
|
||||
*
|
||||
* This function gives PCIe endpoint device drivers the control to change
|
||||
* the power state of a PCIe link for their device.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
|
||||
void *data, u32 options);
|
||||
|
||||
/**
|
||||
* msm_pcie_register_event - register an event with PCIe bus driver.
|
||||
* @reg: event structure
|
||||
*
|
||||
* This function gives PCIe endpoint device drivers an option to register
|
||||
* events with PCIe bus driver.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_register_event(struct msm_pcie_register_event *reg);
|
||||
|
||||
/**
|
||||
* msm_pcie_deregister_event - deregister an event with PCIe bus driver.
|
||||
* @reg: event structure
|
||||
*
|
||||
* This function gives PCIe endpoint device drivers an option to deregister
|
||||
* events with PCIe bus driver.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_deregister_event(struct msm_pcie_register_event *reg);
|
||||
|
||||
/**
|
||||
* msm_pcie_recover_config - recover config space.
|
||||
* @dev: pci device structure
|
||||
*
|
||||
* This function recovers the config space of both RC and Endpoint.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_recover_config(struct pci_dev *dev);
|
||||
|
||||
/**
|
||||
* msm_pcie_enumerate - enumerate Endpoints.
|
||||
* @rc_idx: RC that Endpoints connect to.
|
||||
*
|
||||
* This function enumerates Endpoints connected to RC.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_enumerate(u32 rc_idx);
|
||||
|
||||
/**
|
||||
* msm_pcie_recover_config - recover config space.
|
||||
* @dev: pci device structure
|
||||
*
|
||||
* This function recovers the config space of both RC and Endpoint.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_recover_config(struct pci_dev *dev);
|
||||
|
||||
/**
|
||||
* msm_pcie_shadow_control - control the shadowing of PCIe config space.
|
||||
* @dev: pci device structure
|
||||
* @enable: shadowing should be enabled or disabled
|
||||
*
|
||||
* This function gives PCIe endpoint device drivers the control to enable
|
||||
* or disable the shadowing of PCIe config space.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_shadow_control(struct pci_dev *dev, bool enable);
|
||||
|
||||
/*
|
||||
* msm_pcie_debug_info - run a PCIe specific debug testcase.
|
||||
* @dev: pci device structure
|
||||
* @option: specifies which PCIe debug testcase to execute
|
||||
* @base: PCIe specific range
|
||||
* @offset: offset of destination register
|
||||
* @mask: mask the bit(s) of destination register
|
||||
* @value: value to be written to destination register
|
||||
*
|
||||
* This function gives PCIe endpoint device drivers the control to
|
||||
* run a debug testcase.
|
||||
*
|
||||
* Return: 0 on success, negative value on error
|
||||
*/
|
||||
int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
|
||||
u32 offset, u32 mask, u32 value);
|
||||
|
||||
#else /* !CONFIG_PCI_MSM */
|
||||
static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr,
|
||||
void *user, void *data, u32 options)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_l1ss_timeout_disable(struct pci_dev *pci_dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_l1ss_timeout_enable(struct pci_dev *pci_dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_register_event(struct msm_pcie_register_event *reg)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_deregister_event(struct msm_pcie_register_event *reg)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_recover_config(struct pci_dev *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_enumerate(u32 rc_idx)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_shadow_control(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
|
||||
u32 offset, u32 mask, u32 value)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_PCI_MSM */
|
||||
|
||||
#endif /* __MSM_PCIE_H */
|
||||
Loading…
Reference in a new issue