diff options
Diffstat (limited to 'drivers/pci/of.c')
-rw-r--r-- | drivers/pci/of.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/pci/of.c b/drivers/pci/of.c index cb2e8351c2cc..6c1b81304665 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -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); |