From: Roger Quadros <rogerq@ti.com> To: tony@atomide.com Cc: robh+dt@kernel.org, bcousson@baylibre.com, ssantosh@kernel.org, ohad@wizery.com, bjorn.andersson@linaro.org, s-anna@ti.com, nsekhar@ti.com, t-kristo@ti.com, nsaulnier@ti.com, jreeder@ti.com, m-karicheri2@ti.com, woods.technical@gmail.com, linux-omap@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, rogerq@ti.com Subject: [PATCH 04/17] soc: ti: pruss: Fix system suspend/MStandby config issues Date: Thu, 22 Nov 2018 13:39:00 +0200 [thread overview] Message-ID: <1542886753-17625-5-git-send-email-rogerq@ti.com> (raw) In-Reply-To: <1542886753-17625-1-git-send-email-rogerq@ti.com> From: Suman Anna <s-anna@ti.com> The PRU-ICSS subsystem has a separate PRUSS_CFG module that contains various configuration registers. This includes a control bit STANDBY_INIT in PRUSS_CFG register to initiate a Standby sequence (when set) and trigger a MStandby request to the SoC's PRCM module. This same bit is also used to enable the OCP master ports (when cleared). The system suspend/resume functionality on AM33xx/AM437x/AM57xx SoCs requires all initiators to assert their MStandby signal properly inorder to successfully enter suspend, and resume on a wakeup event. Certain firmwares can enable the OCP master ports through the STANDBY_INIT programming on the firmware side in order to access peripherals or memories external to the PRUSS. This causes a hang in the resume sequence on AM33xx/AM437x boards and requires a board reset to come out of the hang. This patch adds the preliminary System PM callbacks in the PRUSS SoC bus driver, and fixes this system resume hang by setting the STANDBY_INIT in the PM system suspend callback and resetting it back in the PM system resume callback, if so configured. The clearing of the STANDBY_INIT during resume requires an acknowledgment from PRCM and is done through the monitoring of the PRUSS_SYSCFG.SUB_MWAIT bit. NOTE: 1. This patch only adds the PM callbacks with code to fix the System Suspend/Resume hang issue on AM33xx/AM437x SoCs, but does not implement the full context save and restore required for the PRUSS drivers to work across system suspend/resume when the power domain is switched off (L4PER domain is switched OFF on AM335x/AM437x during system suspend/resume, so PRUSS modules do lose context). 2. The PRUSS driver functionality on AM57xx SoCs is not affected that much because the PER power domain to which the PRUSS IPs belong is not switched OFF during suspend/resume. Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Roger Quadros <rogerq@ti.com> --- drivers/soc/ti/pruss_soc_bus.c | 85 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/soc/ti/pruss_soc_bus.c b/drivers/soc/ti/pruss_soc_bus.c index 16b4802..d4da55d2 100644 --- a/drivers/soc/ti/pruss_soc_bus.c +++ b/drivers/soc/ti/pruss_soc_bus.c @@ -7,6 +7,7 @@ * Keerthy <j-keerthy@ti.com> */ +#include <linux/delay.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of_platform.h> @@ -16,13 +17,18 @@ #include <linux/platform_data/ti-pruss.h> +#define SYSCFG_STANDBY_INIT BIT(4) +#define SYSCFG_SUB_MWAIT_READY BIT(5) + /** * struct pruss_soc_bus - PRUSS SoC bus structure * @syscfg: kernel mapped address for SYSCFG register + * @in_standby: flag for storing standby status * @has_reset: cached variable for storing global module reset flag */ struct pruss_soc_bus { void __iomem *syscfg; + bool in_standby; bool has_reset; }; @@ -34,6 +40,81 @@ struct pruss_soc_bus_match_data { bool has_reset; }; +static inline void pruss_soc_bus_rmw(void __iomem *reg, u32 mask, u32 set) +{ + u32 val; + + val = readl_relaxed(reg); + val &= ~mask; + val |= (set & mask); + writel_relaxed(val, reg); +} + +/* + * This function programs the PRUSS_SYSCFG.STANDBY_INIT bit to achieve dual + * functionalities - one is to deassert the MStandby signal to the device + * PRCM, and the other is to enable OCP master ports to allow accesses + * outside of the PRU-ICSS. The function has to wait for the PRCM to + * acknowledge through the monitoring of the PRUSS_SYSCFG.SUB_MWAIT bit. + */ +static +int __maybe_unused pruss_soc_bus_enable_ocp_master_ports(struct device *dev) +{ + struct pruss_soc_bus *psoc_bus = dev_get_drvdata(dev); + u32 syscfg_val, i; + bool ready = false; + + pruss_soc_bus_rmw(psoc_bus->syscfg, SYSCFG_STANDBY_INIT, 0); + + /* wait till we are ready for transactions - delay is arbitrary */ + for (i = 0; i < 10; i++) { + syscfg_val = readl_relaxed(psoc_bus->syscfg); + ready = !(syscfg_val & SYSCFG_SUB_MWAIT_READY); + if (ready) + break; + udelay(5); + } + + if (!ready) { + dev_err(dev, "timeout waiting for SUB_MWAIT_READY\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int __maybe_unused pruss_soc_bus_suspend(struct device *dev) +{ + struct pruss_soc_bus *psoc_bus = dev_get_drvdata(dev); + u32 syscfg_val; + + syscfg_val = readl_relaxed(psoc_bus->syscfg); + psoc_bus->in_standby = syscfg_val & SYSCFG_STANDBY_INIT; + + /* initiate MStandby, undo the MStandby config in probe */ + if (!psoc_bus->in_standby) { + pruss_soc_bus_rmw(psoc_bus->syscfg, SYSCFG_STANDBY_INIT, + SYSCFG_STANDBY_INIT); + } + + return 0; +} + +static int __maybe_unused pruss_soc_bus_resume(struct device *dev) +{ + struct pruss_soc_bus *psoc_bus = dev_get_drvdata(dev); + int ret = 0; + + /* re-enable OCP master ports/disable MStandby */ + if (!psoc_bus->in_standby) { + ret = pruss_soc_bus_enable_ocp_master_ports(dev); + if (ret) + dev_err(dev, "%s failed\n", __func__); + } + + return ret; +} + static int pruss_soc_bus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -126,9 +207,13 @@ static const struct of_device_id pruss_soc_bus_of_match[] = { }; MODULE_DEVICE_TABLE(of, pruss_soc_bus_of_match); +static SIMPLE_DEV_PM_OPS(pruss_soc_bus_pm_ops, + pruss_soc_bus_suspend, pruss_soc_bus_resume); + static struct platform_driver pruss_soc_bus_driver = { .driver = { .name = "pruss-soc-bus", + .pm = &pruss_soc_bus_pm_ops, .of_match_table = pruss_soc_bus_of_match, }, .probe = pruss_soc_bus_probe, -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
WARNING: multiple messages have this Message-ID (diff)
From: Roger Quadros <rogerq@ti.com> To: <tony@atomide.com> Cc: <robh+dt@kernel.org>, <bcousson@baylibre.com>, <ssantosh@kernel.org>, <ohad@wizery.com>, <bjorn.andersson@linaro.org>, <s-anna@ti.com>, <nsekhar@ti.com>, <t-kristo@ti.com>, <nsaulnier@ti.com>, <jreeder@ti.com>, <m-karicheri2@ti.com>, <woods.technical@gmail.com>, <linux-omap@vger.kernel.org>, <linux-remoteproc@vger.kernel.org>, <linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>, <rogerq@ti.com> Subject: [PATCH 04/17] soc: ti: pruss: Fix system suspend/MStandby config issues Date: Thu, 22 Nov 2018 13:39:00 +0200 [thread overview] Message-ID: <1542886753-17625-5-git-send-email-rogerq@ti.com> (raw) In-Reply-To: <1542886753-17625-1-git-send-email-rogerq@ti.com> From: Suman Anna <s-anna@ti.com> The PRU-ICSS subsystem has a separate PRUSS_CFG module that contains various configuration registers. This includes a control bit STANDBY_INIT in PRUSS_CFG register to initiate a Standby sequence (when set) and trigger a MStandby request to the SoC's PRCM module. This same bit is also used to enable the OCP master ports (when cleared). The system suspend/resume functionality on AM33xx/AM437x/AM57xx SoCs requires all initiators to assert their MStandby signal properly inorder to successfully enter suspend, and resume on a wakeup event. Certain firmwares can enable the OCP master ports through the STANDBY_INIT programming on the firmware side in order to access peripherals or memories external to the PRUSS. This causes a hang in the resume sequence on AM33xx/AM437x boards and requires a board reset to come out of the hang. This patch adds the preliminary System PM callbacks in the PRUSS SoC bus driver, and fixes this system resume hang by setting the STANDBY_INIT in the PM system suspend callback and resetting it back in the PM system resume callback, if so configured. The clearing of the STANDBY_INIT during resume requires an acknowledgment from PRCM and is done through the monitoring of the PRUSS_SYSCFG.SUB_MWAIT bit. NOTE: 1. This patch only adds the PM callbacks with code to fix the System Suspend/Resume hang issue on AM33xx/AM437x SoCs, but does not implement the full context save and restore required for the PRUSS drivers to work across system suspend/resume when the power domain is switched off (L4PER domain is switched OFF on AM335x/AM437x during system suspend/resume, so PRUSS modules do lose context). 2. The PRUSS driver functionality on AM57xx SoCs is not affected that much because the PER power domain to which the PRUSS IPs belong is not switched OFF during suspend/resume. Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Roger Quadros <rogerq@ti.com> --- drivers/soc/ti/pruss_soc_bus.c | 85 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/soc/ti/pruss_soc_bus.c b/drivers/soc/ti/pruss_soc_bus.c index 16b4802..d4da55d2 100644 --- a/drivers/soc/ti/pruss_soc_bus.c +++ b/drivers/soc/ti/pruss_soc_bus.c @@ -7,6 +7,7 @@ * Keerthy <j-keerthy@ti.com> */ +#include <linux/delay.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of_platform.h> @@ -16,13 +17,18 @@ #include <linux/platform_data/ti-pruss.h> +#define SYSCFG_STANDBY_INIT BIT(4) +#define SYSCFG_SUB_MWAIT_READY BIT(5) + /** * struct pruss_soc_bus - PRUSS SoC bus structure * @syscfg: kernel mapped address for SYSCFG register + * @in_standby: flag for storing standby status * @has_reset: cached variable for storing global module reset flag */ struct pruss_soc_bus { void __iomem *syscfg; + bool in_standby; bool has_reset; }; @@ -34,6 +40,81 @@ struct pruss_soc_bus_match_data { bool has_reset; }; +static inline void pruss_soc_bus_rmw(void __iomem *reg, u32 mask, u32 set) +{ + u32 val; + + val = readl_relaxed(reg); + val &= ~mask; + val |= (set & mask); + writel_relaxed(val, reg); +} + +/* + * This function programs the PRUSS_SYSCFG.STANDBY_INIT bit to achieve dual + * functionalities - one is to deassert the MStandby signal to the device + * PRCM, and the other is to enable OCP master ports to allow accesses + * outside of the PRU-ICSS. The function has to wait for the PRCM to + * acknowledge through the monitoring of the PRUSS_SYSCFG.SUB_MWAIT bit. + */ +static +int __maybe_unused pruss_soc_bus_enable_ocp_master_ports(struct device *dev) +{ + struct pruss_soc_bus *psoc_bus = dev_get_drvdata(dev); + u32 syscfg_val, i; + bool ready = false; + + pruss_soc_bus_rmw(psoc_bus->syscfg, SYSCFG_STANDBY_INIT, 0); + + /* wait till we are ready for transactions - delay is arbitrary */ + for (i = 0; i < 10; i++) { + syscfg_val = readl_relaxed(psoc_bus->syscfg); + ready = !(syscfg_val & SYSCFG_SUB_MWAIT_READY); + if (ready) + break; + udelay(5); + } + + if (!ready) { + dev_err(dev, "timeout waiting for SUB_MWAIT_READY\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int __maybe_unused pruss_soc_bus_suspend(struct device *dev) +{ + struct pruss_soc_bus *psoc_bus = dev_get_drvdata(dev); + u32 syscfg_val; + + syscfg_val = readl_relaxed(psoc_bus->syscfg); + psoc_bus->in_standby = syscfg_val & SYSCFG_STANDBY_INIT; + + /* initiate MStandby, undo the MStandby config in probe */ + if (!psoc_bus->in_standby) { + pruss_soc_bus_rmw(psoc_bus->syscfg, SYSCFG_STANDBY_INIT, + SYSCFG_STANDBY_INIT); + } + + return 0; +} + +static int __maybe_unused pruss_soc_bus_resume(struct device *dev) +{ + struct pruss_soc_bus *psoc_bus = dev_get_drvdata(dev); + int ret = 0; + + /* re-enable OCP master ports/disable MStandby */ + if (!psoc_bus->in_standby) { + ret = pruss_soc_bus_enable_ocp_master_ports(dev); + if (ret) + dev_err(dev, "%s failed\n", __func__); + } + + return ret; +} + static int pruss_soc_bus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -126,9 +207,13 @@ static const struct of_device_id pruss_soc_bus_of_match[] = { }; MODULE_DEVICE_TABLE(of, pruss_soc_bus_of_match); +static SIMPLE_DEV_PM_OPS(pruss_soc_bus_pm_ops, + pruss_soc_bus_suspend, pruss_soc_bus_resume); + static struct platform_driver pruss_soc_bus_driver = { .driver = { .name = "pruss-soc-bus", + .pm = &pruss_soc_bus_pm_ops, .of_match_table = pruss_soc_bus_of_match, }, .probe = pruss_soc_bus_probe, -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
next prev parent reply other threads:[~2018-11-22 11:39 UTC|newest] Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-11-22 11:38 [PATCH 00/17] Add support for TI PRU ICSS Roger Quadros 2018-11-22 11:38 ` Roger Quadros 2018-11-22 11:38 ` [PATCH 01/17] dt-bindings: remoteproc: Add TI PRUSS bindings Roger Quadros 2018-11-22 11:38 ` Roger Quadros 2018-11-23 16:24 ` Tony Lindgren 2018-11-26 7:47 ` Roger Quadros 2018-11-26 7:47 ` Roger Quadros 2018-11-26 19:35 ` Tony Lindgren 2018-11-26 21:14 ` David Lechner 2018-11-26 23:41 ` Tony Lindgren 2018-11-27 15:15 ` Roger Quadros 2018-11-27 15:15 ` Roger Quadros 2018-11-28 15:42 ` David Lechner 2018-11-29 8:49 ` Roger Quadros 2018-11-29 8:49 ` Roger Quadros 2018-11-29 16:18 ` David Lechner 2018-11-22 11:38 ` [PATCH 02/17] soc: ti: pruss: Define platform data for PRUSS bus driver Roger Quadros 2018-11-22 11:38 ` Roger Quadros 2018-11-22 11:38 ` [PATCH 03/17] soc: ti: pruss: Add pruss_soc_bus platform driver Roger Quadros 2018-11-22 11:38 ` Roger Quadros 2018-11-22 11:39 ` Roger Quadros [this message] 2018-11-22 11:39 ` [PATCH 04/17] soc: ti: pruss: Fix system suspend/MStandby config issues Roger Quadros 2018-11-22 11:39 ` [PATCH 05/17] soc: ti: pruss: Configure SYSCFG properly during probe/remove Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-23 16:26 ` Tony Lindgren 2018-11-22 11:39 ` [PATCH 06/17] soc: ti: pruss: Add a platform driver for PRUSS in TI SoCs Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-26 21:15 ` David Lechner 2018-11-27 15:17 ` Roger Quadros 2018-11-27 15:17 ` Roger Quadros 2018-11-22 11:39 ` [PATCH 07/17] soc: ti: pruss: enable OCP master ports in SYSCFG always Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-23 16:35 ` Tony Lindgren 2018-11-22 11:39 ` [PATCH 08/17] soc: ti: pruss: Add a PRUSS irqchip driver for PRUSS interrupts Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-23 16:37 ` Tony Lindgren 2018-11-26 8:09 ` Roger Quadros 2018-11-26 8:09 ` Roger Quadros 2018-11-26 19:33 ` Tony Lindgren 2018-12-12 15:48 ` Roger Quadros 2018-12-12 15:48 ` Roger Quadros 2018-12-12 17:25 ` Tony Lindgren 2018-11-26 8:09 ` Roger Quadros 2018-11-26 8:09 ` Roger Quadros 2018-11-26 21:17 ` David Lechner 2018-11-27 15:39 ` Roger Quadros 2018-11-27 15:39 ` Roger Quadros 2018-11-28 15:46 ` David Lechner 2018-11-22 11:39 ` [PATCH 09/17] soc: ti: pruss: add pruss_{request,release}_mem_region() API Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-26 21:18 ` David Lechner 2018-11-22 11:39 ` [PATCH 10/17] soc: ti: pruss_intc: Add API to trigger a PRU sysevent Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-26 21:18 ` David Lechner 2018-11-22 11:39 ` [PATCH 11/17] soc: ti: pruss: add pruss_get()/put() API Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-23 2:47 ` kbuild test robot 2018-11-23 2:47 ` kbuild test robot 2018-11-23 2:47 ` kbuild test robot 2018-11-23 9:41 ` Roger Quadros 2018-11-23 9:41 ` Roger Quadros 2018-11-23 8:20 ` Arnd Bergmann 2018-11-23 8:58 ` Tero Kristo 2018-11-23 8:58 ` Tero Kristo 2018-11-23 9:40 ` Roger Quadros 2018-11-23 9:40 ` Roger Quadros 2018-11-26 21:18 ` David Lechner 2018-11-22 11:39 ` [PATCH 12/17] soc: ti: pruss: add pruss_cfg_read()/update() API Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-22 11:39 ` [PATCH 13/17] soc: ti: pruss: export pruss_intc_configure/unconfigure APIs Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-26 21:19 ` David Lechner 2018-11-22 11:39 ` [PATCH 14/17] ARM: OMAP2+: use pdata quirks for PRUSS reset lines on AM335x Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-23 16:40 ` Tony Lindgren 2018-11-22 11:39 ` [PATCH 15/17] ARM: dts: AM33xx: Add the PRU-ICSS DT nodes Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-26 16:37 ` David Lechner 2018-11-22 11:39 ` [PATCH 16/17] ARM: dts: AM33xx: Add PRU system events for virtio Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-22 11:39 ` [PATCH 17/17] ARM: dts: am335x-*: Enable PRU-ICSS nodes Roger Quadros 2018-11-22 11:39 ` Roger Quadros 2018-11-26 16:45 ` David Lechner 2018-12-03 2:04 ` [PATCH 00/17] Add support for TI PRU ICSS Derald D. Woods
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1542886753-17625-5-git-send-email-rogerq@ti.com \ --to=rogerq@ti.com \ --cc=bcousson@baylibre.com \ --cc=bjorn.andersson@linaro.org \ --cc=devicetree@vger.kernel.org \ --cc=jreeder@ti.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-omap@vger.kernel.org \ --cc=linux-remoteproc@vger.kernel.org \ --cc=m-karicheri2@ti.com \ --cc=nsaulnier@ti.com \ --cc=nsekhar@ti.com \ --cc=ohad@wizery.com \ --cc=robh+dt@kernel.org \ --cc=s-anna@ti.com \ --cc=ssantosh@kernel.org \ --cc=t-kristo@ti.com \ --cc=tony@atomide.com \ --cc=woods.technical@gmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.