mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
PCI: dw: rockchip: Add rockchip,keep-power-in-suspend support
This property is used to prevent RC from calling devices to enter D3cold if they need to keep working when system is suspended. The classic user is wireless device and computing cards which need to work standalone when system is suspened. Currently wireless devices deal with it by controlling power and #PERST by themselves because they have rfkill driver which could did it in front of the wireless driver. But computing cards couldn't. In ACPI point of view, we could allow users to configure the D3Cold state for each PCI device through the sysfs attribute 'sys/bus/pci/devices.../d3cold_allowed'. Then the PCIe driver and firmware could work together to meet the requirement. But in DT way, we have to invent a new property to cover both of these. Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> Change-Id: Ia755f48d11f84f292a4aede38d2653b73f8d11b8
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/rfkill-wlan.h>
|
||||
#include <linux/aspm_ext.h>
|
||||
|
||||
@@ -29,6 +31,7 @@
|
||||
#include "../rockchip-pcie-dma.h"
|
||||
#include "pcie-dw-dmatest.h"
|
||||
#include "../../hotplug/gpiophp.h"
|
||||
#include "../../../regulator/internal.h"
|
||||
|
||||
#define RK_PCIE_DBG 0
|
||||
|
||||
@@ -142,6 +145,7 @@ struct rk_pcie {
|
||||
bool is_lpbk;
|
||||
bool is_comp;
|
||||
bool finish_probe;
|
||||
bool keep_power_in_suspend;
|
||||
struct regulator *vpcie3v3;
|
||||
struct irq_domain *irq_domain;
|
||||
raw_spinlock_t intx_lock;
|
||||
@@ -341,6 +345,12 @@ static void rk_pcie_retrain(struct dw_pcie *pci)
|
||||
}
|
||||
}
|
||||
|
||||
static bool rk_pcie_check_keep_power_in_suspend(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
return (!rk_pcie->in_suspend ||
|
||||
(rk_pcie->in_suspend && !rk_pcie->keep_power_in_suspend));
|
||||
}
|
||||
|
||||
static int rk_pcie_establish_link(struct dw_pcie *pci)
|
||||
{
|
||||
int retries, power;
|
||||
@@ -772,6 +782,15 @@ retry_regulator:
|
||||
return PTR_ERR(rk_pcie->phy);
|
||||
}
|
||||
|
||||
rk_pcie->keep_power_in_suspend = device_property_present(&pdev->dev,
|
||||
"rockchip,keep-power-in-suspend");
|
||||
if (rk_pcie->keep_power_in_suspend) {
|
||||
if (IS_ERR(rk_pcie->vpcie3v3))
|
||||
dev_warn(&pdev->dev, "keep power in suspend need vpcie3v3\n");
|
||||
else
|
||||
regulator_suspend_enable(rk_pcie->vpcie3v3->rdev, PM_SUSPEND_MEM);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1444,9 +1463,11 @@ static int rk_pcie_hardware_io_config(struct rk_pcie *rk_pcie)
|
||||
}
|
||||
}
|
||||
|
||||
ret = rk_pcie_enable_power(rk_pcie);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (rk_pcie_check_keep_power_in_suspend(rk_pcie)) {
|
||||
ret = rk_pcie_enable_power(rk_pcie);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
reset_control_assert(rk_pcie->rsts);
|
||||
udelay(10);
|
||||
@@ -1502,8 +1523,10 @@ static int rk_pcie_hardware_io_unconfig(struct rk_pcie *rk_pcie)
|
||||
phy_exit(rk_pcie->phy);
|
||||
clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
|
||||
reset_control_assert(rk_pcie->rsts);
|
||||
rk_pcie_disable_power(rk_pcie);
|
||||
gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0);
|
||||
if (rk_pcie_check_keep_power_in_suspend(rk_pcie)) {
|
||||
rk_pcie_disable_power(rk_pcie);
|
||||
gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user