Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdp7/5fddaab028630dd06ace8e5012cf6798 to your computer and use it in GitHub Desktop.
Save pdp7/5fddaab028630dd06ace8e5012cf6798 to your computer and use it in GitHub Desktop.
patches/drivers/ti/eqep/0002-Avoid-unhandled-fault-when-reading-eQEP-registers.patch
From 692114189bf8635c0be02f7136227b7f7207d2e8 Mon Sep 17 00:00:00 2001
From: Drew Fustini <drew@pdp7.com>
Date: Thu, 2 Feb 2017 03:19:08 -0600
Subject: [PATCH] Avoid unhandled fault when reading eQEP registers
Add pm_runtime_get_sync() before any read or write to the eQEP
memory mapped registers.
---
drivers/misc/tieqep.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/tieqep.c b/drivers/misc/tieqep.c
index d2628847..c2bbc33 100644
--- a/drivers/misc/tieqep.c
+++ b/drivers/misc/tieqep.c
@@ -242,8 +242,13 @@ static ssize_t eqep_get_enabled(struct device *dev, struct device_attribute *att
/* Get the instance structure */
struct eqep_chip *eqep = dev_get_drvdata(dev);
+ u16 enabled = 0;
+
/* Read the qep control register and mask all but the enabled bit */
- u16 enabled = readw(eqep->mmio_base + QEPCTL) & PHEN;
+ enabled = readw(eqep->mmio_base + QEPCTL) & PHEN;
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
/* Return the target in string format */
return sprintf(buf, "%u\n", (enabled) ? 1 : 0);
@@ -262,6 +267,8 @@ static ssize_t eqep_set_enabled(struct device *dev, struct device_attribute *att
if ((rc = kstrtou8(buf, 0, &enabled)))
return rc;
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
/* Get the existing state of QEPCTL */
val = readw(eqep->mmio_base + QEPCTL);
@@ -286,6 +293,8 @@ static ssize_t eqep_get_position(struct device *dev, struct device_attribute *at
struct eqep_chip *eqep = dev_get_drvdata(dev);
s32 position = 0;
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
if (eqep->op_mode == TIEQEP_MODE_ABSOLUTE) {
position = readl(eqep->mmio_base + QPOSCNT);
@@ -308,6 +317,8 @@ static ssize_t eqep_set_position(struct device *dev, struct device_attribute *at
if ((rc = kstrtos32(buf, 0, &position)))
return rc;
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
/*
* If we are in absolute mode, set the position of the encoder,
* discard relative mode because thats pointless
@@ -327,6 +338,8 @@ static ssize_t eqep_get_timer_period(struct device *dev, struct device_attribute
struct eqep_chip *eqep = dev_get_drvdata(dev);
u64 period;
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
/* Convert from counts per interrupt back into period_ns */
period = readl(eqep->mmio_base + QUPRD);
period = period * NSEC_PER_SEC;
@@ -348,6 +361,8 @@ static ssize_t eqep_set_timer_period(struct device *dev, struct device_attribute
if ((rc = kstrtou64(buf, 0, &period)))
return rc;
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
/* Disable the unit timer before modifying its period register */
tmp = readw(eqep->mmio_base + QEPCTL);
tmp &= ~(UTE | QCLM);
@@ -395,6 +410,8 @@ static ssize_t eqep_set_mode(struct device *dev, struct device_attribute *attr,
dev_dbg(dev, "eqep_set_mode:%d\n", tmp_mode);
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
val = readw(eqep->mmio_base + QEPCTL);
if (tmp_mode == TIEQEP_MODE_ABSOLUTE) {
--
2.9.3
@pdp7
Copy link
Author

pdp7 commented Feb 2, 2017

UPDATE:
Fix merged by Robert C. Nelson:
tieqep: add patch to fix unhandled fault on 4.9 kernel
RobertCNelson/ti-linux-kernel-dev@f89418b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment