mirror of https://gitee.com/openkylin/linux.git
PCI: rockchip: Idle inactive PHY(s)
Check the status of all lanes and idle the inactive one(s). Tested-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> [bhelgaas: always set lanes_map, even for legacy_phy case] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Brian Norris <briannorris@chromium.org> Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
This commit is contained in:
parent
90a7612d07
commit
f06c6c41e6
|
@ -15,6 +15,7 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/bitrev.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
@ -112,6 +113,9 @@
|
|||
#define PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT 16
|
||||
#define PCIE_CORE_TXCREDIT_CFG1_MUI_ENCODE(x) \
|
||||
(((x) >> 3) << PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT)
|
||||
#define PCIE_CORE_LANE_MAP (PCIE_CORE_CTRL_MGMT_BASE + 0x200)
|
||||
#define PCIE_CORE_LANE_MAP_MASK 0x0000000f
|
||||
#define PCIE_CORE_LANE_MAP_REVERSE BIT(16)
|
||||
#define PCIE_CORE_INT_STATUS (PCIE_CORE_CTRL_MGMT_BASE + 0x20c)
|
||||
#define PCIE_CORE_INT_PRFPE BIT(0)
|
||||
#define PCIE_CORE_INT_CRFPE BIT(1)
|
||||
|
@ -230,6 +234,7 @@ struct rockchip_pcie {
|
|||
struct regulator *vpcie0v9; /* 0.9V power supply */
|
||||
struct gpio_desc *ep_gpio;
|
||||
u32 lanes;
|
||||
u8 lanes_map;
|
||||
u8 root_bus_nr;
|
||||
int link_gen;
|
||||
struct device *dev;
|
||||
|
@ -302,6 +307,24 @@ static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static u8 rockchip_pcie_lane_map(struct rockchip_pcie *rockchip)
|
||||
{
|
||||
u32 val;
|
||||
u8 map;
|
||||
|
||||
if (rockchip->legacy_phy)
|
||||
return GENMASK(MAX_LANE_NUM - 1, 0);
|
||||
|
||||
val = rockchip_pcie_read(rockchip, PCIE_CORE_LANE_MAP);
|
||||
map = val & PCIE_CORE_LANE_MAP_MASK;
|
||||
|
||||
/* The link may be using a reverse-indexed mapping. */
|
||||
if (val & PCIE_CORE_LANE_MAP_REVERSE)
|
||||
map = bitrev8(map) >> 4;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
|
||||
int where, int size, u32 *val)
|
||||
{
|
||||
|
@ -698,6 +721,15 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
|||
PCIE_CORE_PL_CONF_LANE_SHIFT);
|
||||
dev_dbg(dev, "current link width is x%d\n", status);
|
||||
|
||||
/* Power off unused lane(s) */
|
||||
rockchip->lanes_map = rockchip_pcie_lane_map(rockchip);
|
||||
for (i = 0; i < MAX_LANE_NUM; i++) {
|
||||
if (!(rockchip->lanes_map & BIT(i))) {
|
||||
dev_dbg(dev, "idling lane %d\n", i);
|
||||
phy_power_off(rockchip->phys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID,
|
||||
PCIE_CORE_CONFIG_VENDOR);
|
||||
rockchip_pcie_write(rockchip,
|
||||
|
@ -1349,7 +1381,9 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev)
|
|||
}
|
||||
|
||||
for (i = 0; i < MAX_LANE_NUM; i++) {
|
||||
phy_power_off(rockchip->phys[i]);
|
||||
/* inactive lanes are already powered off */
|
||||
if (rockchip->lanes_map & BIT(i))
|
||||
phy_power_off(rockchip->phys[i]);
|
||||
phy_exit(rockchip->phys[i]);
|
||||
}
|
||||
|
||||
|
@ -1597,7 +1631,9 @@ static int rockchip_pcie_remove(struct platform_device *pdev)
|
|||
irq_domain_remove(rockchip->irq_domain);
|
||||
|
||||
for (i = 0; i < MAX_LANE_NUM; i++) {
|
||||
phy_power_off(rockchip->phys[i]);
|
||||
/* inactive lanes are already powered off */
|
||||
if (rockchip->lanes_map & BIT(i))
|
||||
phy_power_off(rockchip->phys[i]);
|
||||
phy_exit(rockchip->phys[i]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue