NVIDIA: SAUCE: usb: gadget: xudc: use reset control framework for reset
BugLink: https://bugs.launchpad.net/bugs/2080908 There is no XUSB powergating support for some internal platforms Use reset control framework for XUSB controllers. This change also updates the names of old powergate functions for chips do not have powergate support. http://nvbugs/3645739 http://nvbugs/3560606 http://nvbugs/4275301 Signed-off-by: Sing-Han Chen <singhanc@nvidia.com> Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Acked-by: Noah Wager <noah.wager@canonical.com> Acked-by: Jacob Martin <jacob.martin@canonical.com> Signed-off-by: Noah Wager <noah.wager@canonical.com>
This commit is contained in:
committed by
Noah Wager
parent
865e846be6
commit
f7d3041fed
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* NVIDIA Tegra XUSB device mode controller
|
||||
*
|
||||
* Copyright (c) 2013-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2013-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2015, Google Inc.
|
||||
*/
|
||||
|
||||
@@ -501,6 +501,9 @@ struct tegra_xudc {
|
||||
|
||||
struct clk_bulk_data *clks;
|
||||
|
||||
struct reset_control *dev_rst;
|
||||
struct reset_control *ss_rst;
|
||||
|
||||
bool device_mode;
|
||||
struct work_struct usb_role_sw_work;
|
||||
|
||||
@@ -555,6 +558,7 @@ struct tegra_xudc_soc {
|
||||
bool port_reset_quirk;
|
||||
bool port_speed_quirk;
|
||||
bool has_ipfs;
|
||||
bool has_pg_support;
|
||||
};
|
||||
|
||||
static inline u32 fpci_readl(struct tegra_xudc *xudc, unsigned int offset)
|
||||
@@ -3646,6 +3650,7 @@ static struct tegra_xudc_soc tegra210_xudc_soc_data = {
|
||||
.port_reset_quirk = true,
|
||||
.port_speed_quirk = false,
|
||||
.has_ipfs = true,
|
||||
.has_pg_support = true,
|
||||
};
|
||||
|
||||
static struct tegra_xudc_soc tegra186_xudc_soc_data = {
|
||||
@@ -3660,6 +3665,7 @@ static struct tegra_xudc_soc tegra186_xudc_soc_data = {
|
||||
.port_reset_quirk = false,
|
||||
.port_speed_quirk = false,
|
||||
.has_ipfs = false,
|
||||
.has_pg_support = true,
|
||||
};
|
||||
|
||||
static struct tegra_xudc_soc tegra194_xudc_soc_data = {
|
||||
@@ -3674,6 +3680,7 @@ static struct tegra_xudc_soc tegra194_xudc_soc_data = {
|
||||
.port_reset_quirk = false,
|
||||
.port_speed_quirk = true,
|
||||
.has_ipfs = false,
|
||||
.has_pg_support = true,
|
||||
};
|
||||
|
||||
static struct tegra_xudc_soc tegra234_xudc_soc_data = {
|
||||
@@ -3687,6 +3694,7 @@ static struct tegra_xudc_soc tegra234_xudc_soc_data = {
|
||||
.pls_quirk = false,
|
||||
.port_reset_quirk = false,
|
||||
.has_ipfs = false,
|
||||
.has_pg_support = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_xudc_of_match[] = {
|
||||
@@ -3849,9 +3857,25 @@ static int tegra_xudc_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
goto disable_regulator;
|
||||
|
||||
err = tegra_xudc_powerdomain_init(xudc);
|
||||
if (err)
|
||||
goto put_powerdomains;
|
||||
if (xudc->soc->has_pg_support) {
|
||||
err = tegra_xudc_powerdomain_init(xudc);
|
||||
if (err)
|
||||
goto put_powerdomains;
|
||||
} else {
|
||||
xudc->dev_rst = devm_reset_control_get(&pdev->dev, "xusb_dev");
|
||||
if (IS_ERR(xudc->dev_rst)) {
|
||||
err = PTR_ERR(xudc->dev_rst);
|
||||
dev_err(&pdev->dev, "failed to get xusb_dev reset: %d\n", err);
|
||||
goto disable_regulator;
|
||||
}
|
||||
|
||||
xudc->ss_rst = devm_reset_control_get_shared(&pdev->dev, "xusb_ss");
|
||||
if (IS_ERR(xudc->ss_rst)) {
|
||||
err = PTR_ERR(xudc->ss_rst);
|
||||
dev_err(&pdev->dev, "failed to get xusb_ss reset: %d\n", err);
|
||||
goto disable_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
err = tegra_xudc_phy_init(xudc);
|
||||
if (err)
|
||||
@@ -3948,11 +3972,13 @@ static void tegra_xudc_remove(struct platform_device *pdev)
|
||||
tegra_xusb_padctl_put(xudc->padctl);
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc)
|
||||
static int __maybe_unused
|
||||
tegra_xudc_lowpower_enter(struct tegra_xudc *xudc)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
dev_dbg(xudc->dev, "entering ELPG\n");
|
||||
dev_dbg(xudc->dev, "entering low power state\n");
|
||||
|
||||
spin_lock_irqsave(&xudc->lock, flags);
|
||||
|
||||
@@ -3967,16 +3993,31 @@ static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc)
|
||||
|
||||
regulator_bulk_disable(xudc->soc->num_supplies, xudc->supplies);
|
||||
|
||||
dev_dbg(xudc->dev, "entering ELPG done\n");
|
||||
if (!xudc->soc->has_pg_support) {
|
||||
err = reset_control_assert(xudc->dev_rst);
|
||||
if (err) {
|
||||
dev_err(xudc->dev, "failed to assert xusb_dev reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = reset_control_assert(xudc->ss_rst);
|
||||
if (err) {
|
||||
dev_err(xudc->dev, "failed to assert xusb_ss reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(xudc->dev, "entering low power state done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_xudc_unpowergate(struct tegra_xudc *xudc)
|
||||
static int __maybe_unused
|
||||
tegra_xudc_lowpower_exit(struct tegra_xudc *xudc)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
dev_dbg(xudc->dev, "exiting ELPG\n");
|
||||
dev_dbg(xudc->dev, "exiting low power state\n");
|
||||
|
||||
err = regulator_bulk_enable(xudc->soc->num_supplies,
|
||||
xudc->supplies);
|
||||
@@ -3987,6 +4028,20 @@ static int __maybe_unused tegra_xudc_unpowergate(struct tegra_xudc *xudc)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!xudc->soc->has_pg_support) {
|
||||
err = reset_control_deassert(xudc->dev_rst);
|
||||
if (err) {
|
||||
dev_err(xudc->dev, "failed to deassert xusb_dev reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = reset_control_deassert(xudc->ss_rst);
|
||||
if (err) {
|
||||
dev_err(xudc->dev, "failed to deassert xusb_ss reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
tegra_xudc_fpci_ipfs_init(xudc);
|
||||
|
||||
tegra_xudc_device_params_init(xudc);
|
||||
@@ -4002,7 +4057,7 @@ static int __maybe_unused tegra_xudc_unpowergate(struct tegra_xudc *xudc)
|
||||
xudc->powergated = false;
|
||||
spin_unlock_irqrestore(&xudc->lock, flags);
|
||||
|
||||
dev_dbg(xudc->dev, "exiting ELPG done\n");
|
||||
dev_dbg(xudc->dev, "exiting low power state done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4020,7 +4075,7 @@ static int __maybe_unused tegra_xudc_suspend(struct device *dev)
|
||||
if (!pm_runtime_status_suspended(dev)) {
|
||||
/* Forcibly disconnect before powergating. */
|
||||
tegra_xudc_device_mode_off(xudc);
|
||||
tegra_xudc_powergate(xudc);
|
||||
tegra_xudc_lowpower_enter(xudc);
|
||||
}
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
@@ -4034,7 +4089,7 @@ static int __maybe_unused tegra_xudc_resume(struct device *dev)
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
err = tegra_xudc_unpowergate(xudc);
|
||||
err = tegra_xudc_lowpower_exit(xudc);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -4053,14 +4108,14 @@ static int __maybe_unused tegra_xudc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra_xudc *xudc = dev_get_drvdata(dev);
|
||||
|
||||
return tegra_xudc_powergate(xudc);
|
||||
return tegra_xudc_lowpower_enter(xudc);
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_xudc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct tegra_xudc *xudc = dev_get_drvdata(dev);
|
||||
|
||||
return tegra_xudc_unpowergate(xudc);
|
||||
return tegra_xudc_lowpower_exit(xudc);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tegra_xudc_pm_ops = {
|
||||
|
||||
Reference in New Issue
Block a user