@@ -20,7 +20,7 @@ struct tegra_bpmp_ops {
int (*post_response)(struct tegra_bpmp_channel *channel);
int (*post_request)(struct tegra_bpmp_channel *channel);
int (*ring_doorbell)(struct tegra_bpmp *bpmp);
- int (*resume)(struct tegra_bpmp *bpmp);
+ int (*reset)(struct tegra_bpmp *bpmp);
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
@@ -366,7 +366,7 @@ static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
tegra186_bpmp_teardown_channels(bpmp);
}
-static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
+static int tegra186_bpmp_reset(struct tegra_bpmp *bpmp)
{
tegra186_bpmp_reset_channels(bpmp);
@@ -385,5 +385,5 @@ const struct tegra_bpmp_ops tegra186_bpmp_ops = {
.post_response = tegra186_bpmp_post_message,
.post_request = tegra186_bpmp_post_message,
.ring_doorbell = tegra186_bpmp_ring_doorbell,
- .resume = tegra186_bpmp_resume,
+ .reset = tegra186_bpmp_reset,
};
@@ -313,6 +313,14 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
return __tegra_bpmp_channel_write(channel, mrq, flags, data, size);
}
+static int tegra_bpmp_reset(struct tegra_bpmp *bpmp)
+{
+ if (bpmp->soc->ops->reset)
+ return bpmp->soc->ops->reset(bpmp);
+
+ return 0;
+}
+
int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
struct tegra_bpmp_message *msg)
{
@@ -325,6 +333,15 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
if (!tegra_bpmp_message_valid(msg))
return -EINVAL;
+ if (bpmp->needs_reset) {
+ err = tegra_bpmp_reset(bpmp);
+ if (err < 0) {
+ dev_err(bpmp->dev, "Failed to reset the BPMP!\n");
+ return err;
+ }
+ bpmp->needs_reset = false;
+ }
+
channel = bpmp->tx_channel;
spin_lock(&bpmp->atomic_tx_lock);
@@ -364,6 +381,15 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
if (!tegra_bpmp_message_valid(msg))
return -EINVAL;
+ if (bpmp->needs_reset) {
+ err = tegra_bpmp_reset(bpmp);
+ if (err < 0) {
+ dev_err(bpmp->dev, "Failed to reset the BPMP!\n");
+ return err;
+ }
+ bpmp->needs_reset = false;
+ }
+
channel = tegra_bpmp_write_threaded(bpmp, msg->mrq, msg->tx.data,
msg->tx.size);
if (IS_ERR(channel))
@@ -740,6 +766,8 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
if (err < 0)
return err;
+ bpmp->needs_reset = false;
+
err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
tegra_bpmp_mrq_handle_ping, bpmp);
if (err < 0)
@@ -796,18 +824,23 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
return err;
}
-static int __maybe_unused tegra_bpmp_resume(struct device *dev)
+static int __maybe_unused tegra_bpmp_suspend(struct device *dev)
{
struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
- if (bpmp->soc->ops->resume)
- return bpmp->soc->ops->resume(bpmp);
- else
- return 0;
+ /*
+ * If the BPMP has a reset handler then mark as
+ * not ready until on entry to suspend. This flag
+ * is used to trigger the reset after resume.
+ */
+ if (bpmp->soc->ops->reset)
+ bpmp->needs_reset = true;
+
+ return 0;
}
static const struct dev_pm_ops tegra_bpmp_pm_ops = {
- .resume_noirq = tegra_bpmp_resume,
+ .suspend_noirq = tegra_bpmp_suspend,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
@@ -102,6 +102,8 @@ struct tegra_bpmp {
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_mirror;
#endif
+
+ bool needs_reset;
};
struct tegra_bpmp_message {