[PATCH RFC] w1: omap: disable iclk autoidle

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On the gta04 in DM3730, omap_hdq gets stuck whenever
autosuspend is enabled for UART1/2. The system will go into
a lower power state then. According to the TRM, the module has
no way to prevent the ick from being but during a transfer if
autoidle is enabled.
So disable autoidle.
Having omap_hdq working on the gta04 is important for measuring
currents through a bq27000.

The question is what is the best place to do this.
Perhaps better in arch/arm/mach-omap2 somehow, so
no additional exported symbols are needed.
But there seems to be no simple flag to set there.
Maybe we need something like
arch/arm/mach-omap2/mcbsp.c?

And also the affected platforms need to be checked.

Probably omap_hdq_get/put should also be cleaned up and
stuff from there should be put into a runtime_suspend/resume
handler.

Signed-off-by: Andreas Kemnade <andreas@xxxxxxxxxxxx>
---
 drivers/clk/ti/autoidle.c     |  2 ++
 drivers/w1/masters/omap_hdq.c | 27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c
index 7bb9afbe4058..b8970006efd9 100644
--- a/drivers/clk/ti/autoidle.c
+++ b/drivers/clk/ti/autoidle.c
@@ -52,6 +52,7 @@ int omap2_clk_deny_idle(struct clk *clk)
 		c->ops->deny_idle(c);
 	return 0;
 }
+EXPORT_SYMBOL(omap2_clk_deny_idle);
 
 /**
  * omap2_clk_allow_idle - enable autoidle on an OMAP clock
@@ -68,6 +69,7 @@ int omap2_clk_allow_idle(struct clk *clk)
 		c->ops->allow_idle(c);
 	return 0;
 }
+EXPORT_SYMBOL(omap2_clk_allow_idle);
 
 static void _allow_autoidle(struct clk_ti_autoidle *clk)
 {
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 3099052e1243..e3aeba8a1155 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -18,6 +18,8 @@
 #include <linux/sched.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/clk/ti.h>
 
 #include <linux/w1.h>
 
@@ -59,6 +61,14 @@ MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection in HDQ mode");
 
 struct hdq_data {
 	struct device		*dev;
+	/*
+	 * needed to disable autoidle, if system power state is too low
+	 * hdq transactions will not work correctly, although registers
+	 * are accessible.
+	 * According to AM/DM3730 TRM p.2879 the hwmod has to way to
+	 * keep iclk running during a transfer if autoidle is enabled
+	 */
+	struct clk		*ick;
 	void __iomem		*hdq_base;
 	/* lock status update */
 	struct  mutex		hdq_mutex;
@@ -414,6 +424,9 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
 		try_module_get(THIS_MODULE);
 		if (1 == hdq_data->hdq_usecount) {
 
+			if (!IS_ERR_OR_NULL(hdq_data->ick))
+				omap2_clk_deny_idle(hdq_data->ick);
+
 			pm_runtime_get_sync(hdq_data->dev);
 
 			/* make sure HDQ/1W is out of reset */
@@ -460,8 +473,11 @@ static int omap_hdq_put(struct hdq_data *hdq_data)
 	} else {
 		hdq_data->hdq_usecount--;
 		module_put(THIS_MODULE);
-		if (0 == hdq_data->hdq_usecount)
+		if (hdq_data->hdq_usecount == 0) {
 			pm_runtime_put_sync(hdq_data->dev);
+			if (!IS_ERR_OR_NULL(hdq_data->ick))
+				omap2_clk_allow_idle(hdq_data->ick);
+		}
 	}
 	mutex_unlock(&hdq_data->hdq_mutex);
 
@@ -681,8 +697,15 @@ static int omap_hdq_probe(struct platform_device *pdev)
 
 	hdq_data->hdq_usecount = 0;
 	hdq_data->rrw = 0;
+	hdq_data->ick = devm_clk_get(dev, "hdq_ick");
+	if (IS_ERR_OR_NULL(hdq_data->ick))
+		dev_info(dev, "no hdq_ick, lets hope autoidle behaves!");
+
 	mutex_init(&hdq_data->hdq_mutex);
 
+	if (!IS_ERR_OR_NULL(hdq_data->ick))
+		omap2_clk_deny_idle(hdq_data->ick);
+
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0) {
@@ -718,6 +741,8 @@ static int omap_hdq_probe(struct platform_device *pdev)
 	omap_hdq_break(hdq_data);
 
 	pm_runtime_put_sync(&pdev->dev);
+	if (!IS_ERR_OR_NULL(hdq_data->ick))
+		omap2_clk_allow_idle(hdq_data->ick);
 
 	ret = of_property_read_string(pdev->dev.of_node, "ti,mode", &mode);
 	if (ret < 0 || !strcmp(mode, "hdq")) {
-- 
2.11.0




[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux