diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2016-06-13 12:01:51 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-08-18 17:04:57 -0400 |
commit | eec097d43100a8195fd4f678671ecd5d986dd675 (patch) | |
tree | ec874686b415958f9123b68f4ba0f85bae6b8c86 /drivers/pci/pcie/ptm.c | |
parent | 9bb04a0c4e261187be904d05c2bcd1da0eebc20c (diff) |
PCI: Add pci_enable_ptm() for drivers to enable PTM on endpoints
Add an pci_enable_ptm() interface so drivers can enable PTM.
The PCI core enables PTM on PTM Roots and switches automatically, but we
don't enable PTM on endpoints unless a driver requests it.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pcie/ptm.c')
-rw-r--r-- | drivers/pci/pcie/ptm.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c index 48eea4e65247..a14ac94b96dc 100644 --- a/drivers/pci/pcie/ptm.c +++ b/drivers/pci/pcie/ptm.c | |||
@@ -68,3 +68,48 @@ void pci_ptm_init(struct pci_dev *dev) | |||
68 | 68 | ||
69 | pci_ptm_info(dev); | 69 | pci_ptm_info(dev); |
70 | } | 70 | } |
71 | |||
72 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
73 | { | ||
74 | int pos; | ||
75 | u32 cap, ctrl; | ||
76 | struct pci_dev *ups; | ||
77 | |||
78 | if (!pci_is_pcie(dev)) | ||
79 | return -EINVAL; | ||
80 | |||
81 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM); | ||
82 | if (!pos) | ||
83 | return -EINVAL; | ||
84 | |||
85 | pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap); | ||
86 | if (!(cap & PCI_PTM_CAP_REQ)) | ||
87 | return -EINVAL; | ||
88 | |||
89 | /* | ||
90 | * For a PCIe Endpoint, PTM is only useful if the endpoint can | ||
91 | * issue PTM requests to upstream devices that have PTM enabled. | ||
92 | * | ||
93 | * For Root Complex Integrated Endpoints, there is no upstream | ||
94 | * device, so there must be some implementation-specific way to | ||
95 | * associate the endpoint with a time source. | ||
96 | */ | ||
97 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT) { | ||
98 | ups = pci_upstream_bridge(dev); | ||
99 | if (!ups || !ups->ptm_enabled) | ||
100 | return -EINVAL; | ||
101 | } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) { | ||
102 | } else | ||
103 | return -EINVAL; | ||
104 | |||
105 | ctrl = PCI_PTM_CTRL_ENABLE; | ||
106 | pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl); | ||
107 | dev->ptm_enabled = 1; | ||
108 | |||
109 | pci_ptm_info(dev); | ||
110 | |||
111 | if (granularity) | ||
112 | *granularity = 0; | ||
113 | return 0; | ||
114 | } | ||
115 | EXPORT_SYMBOL(pci_enable_ptm); | ||