Skip to content

Instantly share code, notes, and snippets.

@pdp7
Last active February 2, 2017 20:46
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/1db356e758e9ff0c1e570e6ee362c673 to your computer and use it in GitHub Desktop.
Save pdp7/1db356e758e9ff0c1e570e6ee362c673 to your computer and use it in GitHub Desktop.
BeagleBone eQEP Rotary Encoder test

4.1.30-ti-r70

# uname -a
Linux beaglebone 4.1.30-ti-r70 #1 SMP Thu Jan 19 22:51:35

# config-pin p8.11 qep
# config-pin p8.12 qep

# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
-2
<turn the rotary encoder>
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
18

# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/control
auto
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/runtime_enabled
enabled
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/runtime_status
suspended

4.4.44-ti-r85

# uname -a
Linux beaglebone 4.4.44-ti-r85 #1 SMP Fri Jan 27 22:16:52

# config-pin p8.11 qep
# config-pin p8.12 qep

# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
-2
<turn the rotary encoder>
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
18

# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/control
auto
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/runtime_enabled
enabled
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/runtime_status
suspended

4.9.6-ti-r17

# uname -a
Linux beaglebone 4.9.6-ti-r17 #1 SMP PREEMPT Sat Jan 28 11:37:11 UTC 2017 armv7l GNU/Linux

# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/control
auto
# echo on > /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/control
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/control
on
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/power/runtime_status 
active

# config-pin p8.11 qep
# config-pin p8.12 qep

# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
-2
<turn the rotary encoder>
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
46

4.9.6-ti-r18

  • Add eQEP driver patch to avoid unhandled fault:
    • patches/drivers/ti/eqep/0002-Avoid-unhandled-fault-when-reading-eQEP-registers.patch
    • Add pm_runtime_get_sync() before any read or write to the eQEP memory mapped registers
root@beaglebone:~# uname -a
Linux beaglebone 4.9.6-ti-r18 #1 SMP PREEMPT Thu Feb 2 03:50:27 CST 2017 armv7l GNU/Linux
root@beaglebone:~# config-pin p8.11 qep && config-pin p8.12 qep
root@beaglebone:~# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
0
root@beaglebone:~# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
66

4.9.7-ti-r19

New kernel with https://github.com/RobertCNelson/ti-linux-kernel-dev/commit/f89418b8f79dea8a843dab279b7c47c5a4b79ef9

root@beaglebone:~# uname -r
4.9.7-ti-r19
root@beaglebone:~# config-pin p8.11 qep && config-pin p8.12 qep
root@beaglebone:~# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position 
1
root@beaglebone:~# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position 
97
@pdp7
Copy link
Author

pdp7 commented Feb 1, 2017

/boot/uEnv.txt

uname_r=4.9.6-ti-r17
dtb=am335x-boneblack-overlay.dtb
cmdline=coherent_pool=1M quiet cape_universal=enable

@pdp7
Copy link
Author

pdp7 commented Feb 2, 2017

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