1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
From 3514828cb2cf52e545fe71bb7dc2d105d8b0084e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
Date: Sun, 31 Oct 2021 16:07:06 +0100
Subject: [PATCH 48/90] PCI: Add function for parsing
'slot-power-limit-milliwatt' DT property
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add function of_pci_get_slot_power_limit(), which parses the
'slot-power-limit-milliwatt' DT property, returning the value in
milliwatts and in format ready for the PCIe Slot Capabilities Register.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <kabel@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
drivers/pci/of.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.h | 15 ++++++++++
2 files changed, 85 insertions(+)
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index d84381ce82b5..1372da653929 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -627,3 +627,73 @@ int of_pci_get_max_link_speed(struct device_node *node)
return max_link_speed;
}
EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed);
+
+/**
+ * of_pci_get_slot_power_limit - Parses the "slot-power-limit-milliwatt"
+ * property.
+ *
+ * @node: device tree node with the slot power limit information
+ * @slot_power_limit_value: pointer where the value should be stored in PCIe
+ * Slot Capabilities Register format
+ * @slot_power_limit_scale: pointer where the scale should be stored in PCIe
+ * Slot Capabilities Register format
+ *
+ * Returns the slot power limit in milliwatts and if @slot_power_limit_value
+ * and @slot_power_limit_scale pointers are non-NULL, fills in the value and
+ * scale in format used by PCIe Slot Capabilities Register.
+ *
+ * If the property is not found or is invalid, returns 0.
+ */
+u32 of_pci_get_slot_power_limit(struct device_node *node,
+ u8 *slot_power_limit_value,
+ u8 *slot_power_limit_scale)
+{
+ u32 slot_power_limit_mw;
+ u8 value, scale;
+
+ if (of_property_read_u32(node, "slot-power-limit-milliwatt",
+ &slot_power_limit_mw))
+ slot_power_limit_mw = 0;
+
+ /* Calculate Slot Power Limit Value and Slot Power Limit Scale */
+ if (slot_power_limit_mw == 0) {
+ value = 0x00;
+ scale = 0;
+ } else if (slot_power_limit_mw <= 255) {
+ value = slot_power_limit_mw;
+ scale = 3;
+ } else if (slot_power_limit_mw <= 255*10) {
+ value = slot_power_limit_mw / 10;
+ scale = 2;
+ slot_power_limit_mw = slot_power_limit_mw / 10 * 10;
+ } else if (slot_power_limit_mw <= 255*100) {
+ value = slot_power_limit_mw / 100;
+ scale = 1;
+ slot_power_limit_mw = slot_power_limit_mw / 100 * 100;
+ } else if (slot_power_limit_mw <= 239*1000) {
+ value = slot_power_limit_mw / 1000;
+ scale = 0;
+ slot_power_limit_mw = slot_power_limit_mw / 1000 * 1000;
+ } else if (slot_power_limit_mw < 250*1000) {
+ value = 0xEF;
+ scale = 0;
+ slot_power_limit_mw = 239*1000;
+ } else if (slot_power_limit_mw <= 600*1000) {
+ value = 0xF0 + (slot_power_limit_mw / 1000 - 250) / 25;
+ scale = 0;
+ slot_power_limit_mw = slot_power_limit_mw / (1000*25) * (1000*25);
+ } else {
+ value = 0xFE;
+ scale = 0;
+ slot_power_limit_mw = 600*1000;
+ }
+
+ if (slot_power_limit_value)
+ *slot_power_limit_value = value;
+
+ if (slot_power_limit_scale)
+ *slot_power_limit_scale = scale;
+
+ return slot_power_limit_mw;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_slot_power_limit);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 1cce56c2aea0..9352278141be 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -665,6 +665,9 @@ struct device_node;
int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
int of_get_pci_domain_nr(struct device_node *node);
int of_pci_get_max_link_speed(struct device_node *node);
+u32 of_pci_get_slot_power_limit(struct device_node *node,
+ u8 *slot_power_limit_value,
+ u8 *slot_power_limit_scale);
void pci_set_of_node(struct pci_dev *dev);
void pci_release_of_node(struct pci_dev *dev);
void pci_set_bus_of_node(struct pci_bus *bus);
@@ -691,6 +694,18 @@ of_pci_get_max_link_speed(struct device_node *node)
return -EINVAL;
}
+static inline u32
+of_pci_get_slot_power_limit(struct device_node *node,
+ u8 *slot_power_limit_value,
+ u8 *slot_power_limit_scale)
+{
+ if (slot_power_limit_value)
+ *slot_power_limit_value = 0;
+ if (slot_power_limit_scale)
+ *slot_power_limit_scale = 0;
+ return 0;
+}
+
static inline void pci_set_of_node(struct pci_dev *dev) { }
static inline void pci_release_of_node(struct pci_dev *dev) { }
static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
--
2.34.1
|