Commit 35662423 authored by Pali Rohár's avatar Pali Rohár Committed by Lorenzo Pieralisi
Browse files

PCI: Add function for parsing 'slot-power-limit-milliwatt' DT property

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.

Link: https://lore.kernel.org/r/20220412094946.27069-4-pali@kernel.org


Signed-off-by: default avatarPali Rohár <pali@kernel.org>
Signed-off-by: default avatarMarek Behún <kabel@kernel.org>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: default avatarRob Herring <robh@kernel.org>
Reviewed-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent e8e7fbb6
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -633,3 +633,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);
+15 −0
Original line number Diff line number Diff line
@@ -627,6 +627,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);
@@ -653,6 +656,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) { }