From 462a088c474832b19ff2730de1e6bea66d399c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Sat, 15 Oct 2022 23:01:29 +0200 Subject: Add Turris kernel (includes patches from OpenWrt) --- ...dd-support-for-sending-Set_Slot_Power_Lim.patch | 210 +++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 pkgs/patches-linux-5.15/0049-PCI-mvebu-Add-support-for-sending-Set_Slot_Power_Lim.patch (limited to 'pkgs/patches-linux-5.15/0049-PCI-mvebu-Add-support-for-sending-Set_Slot_Power_Lim.patch') diff --git a/pkgs/patches-linux-5.15/0049-PCI-mvebu-Add-support-for-sending-Set_Slot_Power_Lim.patch b/pkgs/patches-linux-5.15/0049-PCI-mvebu-Add-support-for-sending-Set_Slot_Power_Lim.patch new file mode 100644 index 0000000..4c526f6 --- /dev/null +++ b/pkgs/patches-linux-5.15/0049-PCI-mvebu-Add-support-for-sending-Set_Slot_Power_Lim.patch @@ -0,0 +1,210 @@ +From 5c87d5ff707236098214303289cd5724aebbd0ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 17 Sep 2021 14:25:33 +0200 +Subject: [PATCH 49/90] PCI: mvebu: Add support for sending + Set_Slot_Power_Limit message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If DT supplies the 'slot-power-limit-milliwatt' property, program +the value in the Slot Power Limit in the Slot Capabilities register +and program the Root Port to send a Set_Slot_Power_Limit Message +when the Link transitions to DL_Up. + +Signed-off-by: Pali Rohár +Reviewed-by: Rob Herring +--- + drivers/pci/controller/pci-mvebu.c | 97 ++++++++++++++++++++++++++++-- + 1 file changed, 92 insertions(+), 5 deletions(-) + +diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c +index c9311829dfe3..3c48b15e3948 100644 +--- a/drivers/pci/controller/pci-mvebu.c ++++ b/drivers/pci/controller/pci-mvebu.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -66,6 +67,12 @@ + #define PCIE_STAT_BUS 0xff00 + #define PCIE_STAT_DEV 0x1f0000 + #define PCIE_STAT_LINK_DOWN BIT(0) ++#define PCIE_SSPL_OFF 0x1a0c ++#define PCIE_SSPL_VALUE_SHIFT 0 ++#define PCIE_SSPL_VALUE_MASK GENMASK(7, 0) ++#define PCIE_SSPL_SCALE_SHIFT 8 ++#define PCIE_SSPL_SCALE_MASK GENMASK(9, 8) ++#define PCIE_SSPL_ENABLE BIT(16) + #define PCIE_RC_RTSTA 0x1a14 + #define PCIE_DEBUG_CTRL 0x1a60 + #define PCIE_DEBUG_SOFT_RESET BIT(20) +@@ -111,6 +118,8 @@ struct mvebu_pcie_port { + struct mvebu_pcie_window iowin; + u32 saved_pcie_stat; + struct resource regs; ++ u8 slot_power_limit_value; ++ u8 slot_power_limit_scale; + struct irq_domain *intx_irq_domain; + raw_spinlock_t irq_lock; + int intx_irq; +@@ -239,7 +248,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) + + static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) + { +- u32 ctrl, lnkcap, cmd, dev_rev, unmask; ++ u32 ctrl, lnkcap, cmd, dev_rev, unmask, sspl; + + /* Setup PCIe controller to Root Complex mode. */ + ctrl = mvebu_readl(port, PCIE_CTRL_OFF); +@@ -292,6 +301,20 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) + /* Point PCIe unit MBUS decode windows to DRAM space. */ + mvebu_pcie_setup_wins(port); + ++ /* ++ * Program Root Port to automatically send Set_Slot_Power_Limit ++ * PCIe Message when changing status from Dl_Down to Dl_Up and valid ++ * slot power limit was specified. ++ */ ++ sspl = mvebu_readl(port, PCIE_SSPL_OFF); ++ sspl &= ~(PCIE_SSPL_VALUE_MASK | PCIE_SSPL_SCALE_MASK | PCIE_SSPL_ENABLE); ++ if (port->slot_power_limit_value) { ++ sspl |= port->slot_power_limit_value << PCIE_SSPL_VALUE_SHIFT; ++ sspl |= port->slot_power_limit_scale << PCIE_SSPL_SCALE_SHIFT; ++ sspl |= PCIE_SSPL_ENABLE; ++ } ++ mvebu_writel(port, sspl, PCIE_SSPL_OFF); ++ + /* Mask all interrupt sources. */ + mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF); + +@@ -633,9 +656,24 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, + (PCI_EXP_LNKSTA_DLLLA << 16) : 0); + break; + +- case PCI_EXP_SLTCTL: +- *value = PCI_EXP_SLTSTA_PDS << 16; ++ case PCI_EXP_SLTCTL: { ++ u16 slotctl = le16_to_cpu(bridge->pcie_conf.slotctl); ++ u16 slotsta = le16_to_cpu(bridge->pcie_conf.slotsta); ++ u32 val = 0; ++ /* ++ * When slot power limit was not specified in DT then ++ * ASPL_DISABLE bit is stored only in emulated config space. ++ * Otherwise reflect status of PCIE_SSPL_ENABLE bit in HW. ++ */ ++ if (!port->slot_power_limit_value) ++ val |= slotctl & PCI_EXP_SLTCTL_ASPL_DISABLE; ++ else if (!(mvebu_readl(port, PCIE_SSPL_OFF) & PCIE_SSPL_ENABLE)) ++ val |= PCI_EXP_SLTCTL_ASPL_DISABLE; ++ /* This callback is 32-bit and in high bits is slot status. */ ++ val |= slotsta << 16; ++ *value = val; + break; ++ } + + case PCI_EXP_RTSTA: + *value = mvebu_readl(port, PCIE_RC_RTSTA); +@@ -779,6 +817,22 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, + mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL); + break; + ++ case PCI_EXP_SLTCTL: ++ /* ++ * Allow to change PCIE_SSPL_ENABLE bit only when slot power ++ * limit was specified in DT and configured into HW. ++ */ ++ if ((mask & PCI_EXP_SLTCTL_ASPL_DISABLE) && ++ port->slot_power_limit_value) { ++ u32 sspl = mvebu_readl(port, PCIE_SSPL_OFF); ++ if (new & PCI_EXP_SLTCTL_ASPL_DISABLE) ++ sspl &= ~PCIE_SSPL_ENABLE; ++ else ++ sspl |= PCIE_SSPL_ENABLE; ++ mvebu_writel(port, sspl, PCIE_SSPL_OFF); ++ } ++ break; ++ + case PCI_EXP_RTSTA: + /* + * PME Status bit in Root Status Register (PCIE_RC_RTSTA) +@@ -873,8 +927,26 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) + /* + * Older mvebu hardware provides PCIe Capability structure only in + * version 1. New hardware provides it in version 2. ++ * Enable slot support which is emulated. + */ +- bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver); ++ bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver | PCI_EXP_FLAGS_SLOT); ++ ++ /* ++ * Set Presence Detect State bit permanently as there is no support for ++ * unplugging PCIe card from the slot. Assume that PCIe card is always ++ * connected in slot. ++ * ++ * Set physical slot number to port+1 as mvebu ports are indexed from ++ * zero and zero value is reserved for ports within the same silicon ++ * as Root Port which is not mvebu case. ++ * ++ * Also set correct slot power limit. ++ */ ++ bridge->pcie_conf.slotcap = cpu_to_le32( ++ FIELD_PREP(PCI_EXP_SLTCAP_SPLV, port->slot_power_limit_value) | ++ FIELD_PREP(PCI_EXP_SLTCAP_SPLS, port->slot_power_limit_scale) | ++ FIELD_PREP(PCI_EXP_SLTCAP_PSN, port->port+1)); ++ bridge->pcie_conf.slotsta = cpu_to_le16(PCI_EXP_SLTSTA_PDS); + + bridge->subsystem_vendor_id = ssdev_id & 0xffff; + bridge->subsystem_id = ssdev_id >> 16; +@@ -1198,6 +1270,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, + { + struct device *dev = &pcie->pdev->dev; + enum of_gpio_flags flags; ++ u32 slot_power_limit; + int reset_gpio, ret; + u32 num_lanes; + +@@ -1298,6 +1371,15 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, + port->reset_gpio = gpio_to_desc(reset_gpio); + } + ++ slot_power_limit = of_pci_get_slot_power_limit(child, ++ &port->slot_power_limit_value, ++ &port->slot_power_limit_scale); ++ if (slot_power_limit) ++ dev_info(dev, "%s: Slot power limit %u.%uW\n", ++ port->name, ++ slot_power_limit / 1000, ++ (slot_power_limit / 100) % 10); ++ + port->clk = of_clk_get_by_name(child, NULL); + if (IS_ERR(port->clk)) { + dev_err(dev, "%s: cannot get clock\n", port->name); +@@ -1595,7 +1677,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev) + { + struct mvebu_pcie *pcie = platform_get_drvdata(pdev); + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); +- u32 cmd; ++ u32 cmd, sspl; + int i; + + /* Remove PCI bus with all devices. */ +@@ -1632,6 +1714,11 @@ static int mvebu_pcie_remove(struct platform_device *pdev) + /* Free config space for emulated root bridge. */ + pci_bridge_emul_cleanup(&port->bridge); + ++ /* Disable sending Set_Slot_Power_Limit PCIe Message. */ ++ sspl = mvebu_readl(port, PCIE_SSPL_OFF); ++ sspl &= ~(PCIE_SSPL_VALUE_MASK | PCIE_SSPL_SCALE_MASK | PCIE_SSPL_ENABLE); ++ mvebu_writel(port, sspl, PCIE_SSPL_OFF); ++ + /* Disable and clear BARs and windows. */ + mvebu_pcie_disable_wins(port); + +-- +2.34.1 + -- cgit v1.2.3