aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorJonathan Yong <jonathan.yong@intel.com>2016-06-11 15:13:38 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-08-15 14:44:08 -0400
commit9bb04a0c4e261187be904d05c2bcd1da0eebc20c (patch)
tree725a72656a45640205c5d05885dc9c3fd41f01e0 /drivers/pci/pcie
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
PCI: Add Precision Time Measurement (PTM) support
Add Precision Time Measurement (PTM) support (see PCIe r3.1, sec 6.22). Enable PTM on PTM Root devices and switch ports. This does not enable PTM on endpoints. There currently are no PTM-capable devices on the market, but it is expected to be supported by the Intel Apollo Lake platform. [bhelgaas: complete rework] Signed-off-by: Jonathan Yong <jonathan.yong@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/Kconfig11
-rw-r--r--drivers/pci/pcie/Makefile1
-rw-r--r--drivers/pci/pcie/ptm.c70
3 files changed, 82 insertions, 0 deletions
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 7fcea75afa4c..7ce77635e5ad 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -92,3 +92,14 @@ config PCIE_DPC
92 will be handled by the DPC driver. If your system doesn't 92 will be handled by the DPC driver. If your system doesn't
93 have this capability or you do not want to use this feature, 93 have this capability or you do not want to use this feature,
94 it is safe to answer N. 94 it is safe to answer N.
95
96config PCIE_PTM
97 bool "PCIe Precision Time Measurement support"
98 default n
99 depends on PCIEPORTBUS
100 help
101 This enables PCI Express Precision Time Measurement (PTM)
102 support.
103
104 This is only useful if you have devices that support PTM, but it
105 is safe to enable even if you don't.
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index b24525b3dec1..36e35ea8fde7 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PCIEAER) += aer/
16obj-$(CONFIG_PCIE_PME) += pme.o 16obj-$(CONFIG_PCIE_PME) += pme.o
17 17
18obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o 18obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o
19obj-$(CONFIG_PCIE_PTM) += ptm.o
diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c
new file mode 100644
index 000000000000..48eea4e65247
--- /dev/null
+++ b/drivers/pci/pcie/ptm.c
@@ -0,0 +1,70 @@
1/*
2 * PCI Express Precision Time Measurement
3 * Copyright (c) 2016, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/pci.h>
18#include "../pci.h"
19
20static void pci_ptm_info(struct pci_dev *dev)
21{
22 dev_info(&dev->dev, "PTM enabled%s\n", dev->ptm_root ? " (root)" : "");
23}
24
25void pci_ptm_init(struct pci_dev *dev)
26{
27 int pos;
28 u32 cap, ctrl;
29 struct pci_dev *ups;
30
31 if (!pci_is_pcie(dev))
32 return;
33
34 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM);
35 if (!pos)
36 return;
37
38 /*
39 * Enable PTM only on interior devices (root ports, switch ports,
40 * etc.) on the assumption that it causes no link traffic until an
41 * endpoint enables it.
42 */
43 if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT ||
44 pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END))
45 return;
46
47 pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap);
48
49 /*
50 * There's no point in enabling PTM unless it's enabled in the
51 * upstream device or this device can be a PTM Root itself. Per
52 * the spec recommendation (PCIe r3.1, sec 7.32.3), select the
53 * furthest upstream Time Source as the PTM Root.
54 */
55 ups = pci_upstream_bridge(dev);
56 if (ups && ups->ptm_enabled) {
57 ctrl = PCI_PTM_CTRL_ENABLE;
58 } else {
59 if (cap & PCI_PTM_CAP_ROOT) {
60 ctrl = PCI_PTM_CTRL_ENABLE | PCI_PTM_CTRL_ROOT;
61 dev->ptm_root = 1;
62 } else
63 return;
64 }
65
66 pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl);
67 dev->ptm_enabled = 1;
68
69 pci_ptm_info(dev);
70}