Skip to content

Instantly share code, notes, and snippets.

@pdp7
Last active February 2, 2017 19:24
Show Gist options
  • Save pdp7/fe07082d23f2bfbc362c733a7b0aea72 to your computer and use it in GitHub Desktop.
Save pdp7/fe07082d23f2bfbc362c733a7b0aea72 to your computer and use it in GitHub Desktop.
TI eQEP Rotary Encoder beaglebone 4.9.5-ti-r16
Has anyone tested the eQEP driver with the 4.9 kernel?

I'm attempting to use it with the 4.9.5-ti-r16 from 2017-01-23.

I get a Segmentation Fault when I read the position:
# config-pin p8.11 qep
# config-pin p8.12 qep
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position

It appears to occur in:
(eqep_get_position [tieqep]) from [<c08930d0>] (dev_attr_show+0x2c/0x58)

More details:
https://gist.github.com/pdp7/fe07082d23f2bfbc362c733a7b0aea72

thanks,
drew
# uname -r
4.9.5-ti-r16
# config-pin p8.11 qep
# config-pin p8.12 qep
# cat /sys/devices/platform/bone_capemgr/slots
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
[ 2591.653471] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa304180
[ 2591.661300] pgd = dc51c000
[ 2591.664065] [fa304180] *pgd=48211452(bad)
[ 2591.668208] Internal error: : 1028 [#1] PREEMPT SMP ARM
[ 2591.673514] Modules linked in: c_can_platform c_can can_dev pwm_tiecap spi_omap2_mcspi omap_aes_driver crypto_engine omap_sham omap_rng rng_core evdev tps65217_charger uio_pdrv_genirq uio cpufreq_conservative cpufreq_ondemand usb_f_acm u_serial cpufreq_userspace usb_f_rndis g_multi usb_f_mass_storage u_ether cpufreq_powersave libcomposite 8021q garp mrp stp llc spidev tieqep pwm_tiehrpwm
[ 2591.708950] CPU: 0 PID: 2110 Comm: cat Not tainted 4.9.5-ti-r16 #1
[ 2591.715219] Hardware name: Generic AM33XX (Flattened Device Tree)
[ 2591.721401] task: da857780 task.stack: da8ea000
[ 2591.726046] PC is at eqep_get_position+0x68/0x90 [tieqep]
[ 2591.731551] LR is at dev_attr_show+0x2c/0x58
[ 2591.735896] pc : [<bf005310>]    lr : [<c08930d0>]    psr: 600f0013
sp : da8ebe30  ip : 00000000  fp : da8ebe44
[ 2591.747517] r10: 00000001  r9 : dace8080  r8 : dabf5618
[ 2591.752873] r7 : dc3ba000  r6 : c0d85758  r5 : dc3ba000  r4 : dace8d80
[ 2591.759524] r3 : fa304180  r2 : dc3ba000  r1 : bf00652c  r0 : dabf5610
[ 2591.766179] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[ 2591.773446] Control: 10c5387d  Table: 9c51c019  DAC: 00000051
[ 2591.779308] Process cat (pid: 2110, stack limit = 0xda8ea218)
[ 2591.785171] Stack: (0xda8ebe30 to 0xda8ec000)
[ 2591.789640] be20:                                     dace8d80 bf00652c da8ebe5c da8ebe48
[ 2591.798007] be40: c08930d0 bf0052b4 dace8d80 00001000 da8ebe84 da8ebe60 c035f920 c08930b0
[ 2591.806373] be60: dace8d80 00000000 dab20180 c130414c da8ebf70 00000001 da8ebe94 da8ebe88
[ 2591.814739] be80: c035e2d0 c035f894 da8ebef4 da8ebe98 c0300d58 c035e2a8 da3305c0 da8ebf70
[ 2591.823104] bea0: dace8db0 b6d14000 da8ebeb0 00020000 00000000 00000000 00020000 dab20188
[ 2591.831469] bec0: 00000004 00040905 00000000 00020000 dab20180 b6d14000 da8ebf70 b6d14000
[ 2591.839835] bee0: dace8080 00000000 da8ebf2c da8ebef8 c035f0a0 c0300b7c da8ebf3c da8ebf08
[ 2591.848200] bf00: c02d8928 00020000 dab20180 b6d14000 da8ebf70 b6d14000 da8ea000 00000000
[ 2591.856566] bf20: da8ebf3c da8ebf30 c02d7c0c c035ef78 da8ebf6c da8ebf40 c02d8a68 c02d7bf0
[ 2591.864931] bf40: 000b6d13 c02fa7c8 da8ebf6c dab20180 c130414c dab20180 00020000 b6d14000
[ 2591.873296] bf60: da8ebfa4 da8ebf70 c02d9d04 c02d89d8 00000000 00000000 00000022 00040905
[ 2591.881661] bf80: 00000000 00020000 00020000 b6d14000 00000003 c01092c4 00000000 da8ebfa8
[ 2591.890025] bfa0: c0109100 c02d9cac 00020000 00020000 00000003 b6d14000 00020000 000271c4
[ 2591.898389] bfc0: 00020000 00020000 b6d14000 00000003 7fffe000 00000000 00000000 00020000
[ 2591.906753] bfe0: 00000000 be8b1a64 00013835 b6f49ea6 400f0030 00000003 00000000 00000000
[ 2591.915165] [<bf005310>] (eqep_get_position [tieqep]) from [<c08930d0>] (dev_attr_show+0x2c/0x58)
[ 2591.924261] [<c08930d0>] (dev_attr_show) from [<c035f920>] (sysfs_kf_seq_show+0x98/0x108)
[ 2591.932643] [<c035f920>] (sysfs_kf_seq_show) from [<c035e2d0>] (kernfs_seq_show+0x34/0x38)
[ 2591.941120] [<c035e2d0>] (kernfs_seq_show) from [<c0300d58>] (seq_read+0x1e8/0x538)
[ 2591.948972] [<c0300d58>] (seq_read) from [<c035f0a0>] (kernfs_fop_read+0x134/0x1c0)
[ 2591.956817] [<c035f0a0>] (kernfs_fop_read) from [<c02d7c0c>] (__vfs_read+0x28/0x48)
[ 2591.964660] [<c02d7c0c>] (__vfs_read) from [<c02d8a68>] (vfs_read+0x9c/0x168)
[ 2591.971942] [<c02d8a68>] (vfs_read) from [<c02d9d04>] (SyS_read+0x64/0xcc)
[ 2591.978974] [<c02d9d04>] (SyS_read) from [<c0109100>] (ret_fast_syscall+0x0/0x3c)
[ 2591.986643] Code: e1a04003 e320f000 eafffff3 e5933004 (e5934000) 
[ 2591.992891] ---[ end trace 98580f83455e4632 ]---
root@beaglebone:~# 
@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

I've experimenting more with this eQEP error on the 4.9 kernel:
https://gist.github.com/pdp7/fe07082d23f2bfbc362c733a7b0aea72

From drivers/misc/tieqep.c at found in this patch:
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.9.y/patches/drivers/ti/eqep

This readl() runs OK in eqep_probe():
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.9.y/patches/drivers/ti/eqep#L401

Line 697: dev_info(&pdev->dev, "QPOSCNT:0x%08x\n", readl(eqep->mmio_base + QPOSCNT));

But the same readl() causes a seg fault in eqep_get_position():
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.9.y/patches/drivers/ti/eqep#L401

Line 401: position = readl(eqep->mmio_base + QPOSCNT);

I'm not sure what the difference is. Maybe the memory mapping changes in between the probe and reading the sysfs file?

Any ideas?

thanks,
drew

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

iomem

root@beaglebone:~# cat /proc/iomem|grep eqep
48300180-483001ff : /ocp/epwmss@48300000/eqep@0x48300180
48302180-483021ff : /ocp/epwmss@48302000/eqep@0x48302180
48304180-483041ff : /ocp/epwmss@48304000/eqep@0x48304180
root@beaglebone:~# cat /proc/iomem
40300000-4030ffff : 40300000.ocmcram
44d00000-44d03fff : umem
44d80000-44d81fff : dmem
44e07000-44e07fff : /ocp/gpio@44e07000
44e09000-44e0901f : serial
44e0b000-44e0bfff : /ocp/i2c@44e0b000
44e10620-44e1062f : phy_ctrl
44e10648-44e1064b : wakeup
44e10650-44e10653 : gmii-sel
44e10800-44e10a37 : pinctrl-single
44e10f90-44e10fcf : /ocp/l4_wkup@44c00000/scm@210000/dma-router@f90
44e11324-44e11347 : /ocp/l4_wkup@44c00000/scm@210000/wkup_m3_ipc@1324
44e35000-44e35fff : /ocp/wdt@44e35000
44e3e000-44e3efff : /ocp/rtc@44e3e000
47401000-474011ff : control
47401400-474017ff : mc
  47401400-474017ff : mc
47401800-474019ff : control
47401c00-47401fff : mc
  47401c00-47401fff : mc
48022000-4802201f : serial
48024000-4802401f : serial
4802a000-4802afff : /ocp/i2c@4802a000
48030100-480304ff : /ocp/spi@48030000
48042000-480423ff : /ocp/timer@48042000
48044000-480443ff : /ocp/timer@48044000
48046000-480463ff : /ocp/timer@48046000
48048000-480483ff : /ocp/timer@48048000
4804a000-4804a3ff : /ocp/timer@4804a000
4804c000-4804cfff : /ocp/gpio@4804c000
48060000-48060fff : /ocp/mmc@48060000
480c8000-480c81ff : /ocp/mailbox@480C8000
4819c000-4819cfff : /ocp/i2c@4819c000
481a0100-481a04ff : /ocp/spi@481a0000
481a8000-481a801f : serial
481aa000-481aa01f : serial
481ac000-481acfff : /ocp/gpio@481ac000
481ae000-481aefff : /ocp/gpio@481ae000
48300100-4830017f : /ocp/epwmss@48300000/ecap@48300100
48300180-483001ff : /ocp/epwmss@48300000/eqep@0x48300180
48300200-4830027f : /ocp/epwmss@48300000/pwm@48300200
48302100-4830217f : /ocp/epwmss@48302000/ecap@48302100
48302180-483021ff : /ocp/epwmss@48302000/eqep@0x48302180
48302200-4830227f : /ocp/epwmss@48302000/pwm@48302200
48304100-4830417f : /ocp/epwmss@48304000/ecap@48304100
48304180-483041ff : /ocp/epwmss@48304000/eqep@0x48304180
48304200-4830427f : /ocp/epwmss@48304000/pwm@48304200
48310000-48311fff : /ocp/rng@48310000
49000000-4900ffff : edma3_cc
4a100000-4a1007ff : /ocp/ethernet@4a100000
4a101000-4a1010ff : /ocp/ethernet@4a100000/mdio@4a101000
4a101200-4a1012ff : /ocp/ethernet@4a100000
4c000000-4c000fff : /ocp/emif@4c000000
53100000-531001ff : /ocp/sham@53100000
53500000-5350009f : /ocp/aes@53500000
80000000-9fdfffff : System RAM
  80008000-80dfffff : Kernel code

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

Boot

root@beaglebone:~# dmesg |grep eqep   
[   52.172982] kobject: '48300180.eqep' (d8024018): kobject_add_internal: parent: '48300000.epwmss', set: 'devices'
[   52.173223] kobject: '48300180.eqep' (d8024018): kobject_uevent_env
[   52.173245] kobject: '48300180.eqep' (d8024018): fill_kobj_path: path = '/devices/platform/ocp/48300000.epwmss/48300180.eqep'
[   52.174442] eqep 48300180.eqep: ver. 1.0
[   52.174801] eqep 48300180.eqep: count_mode:0
[   52.174816] eqep 48300180.eqep: invert_qa:1
[   52.174827] eqep 48300180.eqep: invert_qb:1
[   52.174838] eqep 48300180.eqep: invert_qi:0
[   52.174848] eqep 48300180.eqep: invert_qs:0
[   52.174858] eqep 48300180.eqep: swap_inputs:0
[   52.174868] eqep 48300180.eqep: QDECCTL:0x0180
[   52.174878] eqep 48300180.eqep: QPOSINIT:0x00000000
[   52.174886] eqep 48300180.eqep: QPOSMAX:0xffffffff
[   52.174895] eqep 48300180.eqep: QPOSCNT:0x00000000
[   52.174905] eqep 48300180.eqep: omit_interrupt:0
[   52.174914] eqep 48300180.eqep: QEINT:0x0800
[   52.174923] eqep 48300180.eqep: QUPRD:0x05f5e100
[   52.174932] eqep 48300180.eqep: QEPCTL:0x009e write
[   52.174940] eqep 48300180.eqep: QEPCTL:0x009e read
[   52.174986] eqep 48300180.eqep: irq:190, clk_rate:100000000
[   52.198389] kobject: '48302180.eqep' (d8030018): kobject_add_internal: parent: '48302000.epwmss', set: 'devices'
[   52.198645] kobject: '48302180.eqep' (d8030018): kobject_uevent_env
[   52.198667] kobject: '48302180.eqep' (d8030018): fill_kobj_path: path = '/devices/platform/ocp/48302000.epwmss/48302180.eqep'
[   52.199728] eqep 48302180.eqep: ver. 1.0
[   52.200039] eqep 48302180.eqep: count_mode:0
[   52.200052] eqep 48302180.eqep: invert_qa:1
[   52.200064] eqep 48302180.eqep: invert_qb:1
[   52.200074] eqep 48302180.eqep: invert_qi:0
[   52.200085] eqep 48302180.eqep: invert_qs:0
[   52.200095] eqep 48302180.eqep: swap_inputs:0
[   52.200105] eqep 48302180.eqep: QDECCTL:0x0180
[   52.200114] eqep 48302180.eqep: QPOSINIT:0x00000000
[   52.200123] eqep 48302180.eqep: QPOSMAX:0xffffffff
[   52.200132] eqep 48302180.eqep: QPOSCNT:0x00000000
[   52.200142] eqep 48302180.eqep: omit_interrupt:0
[   52.200151] eqep 48302180.eqep: QEINT:0x0800
[   52.200161] eqep 48302180.eqep: QUPRD:0x05f5e100
[   52.200169] eqep 48302180.eqep: QEPCTL:0x009e write
[   52.200178] eqep 48302180.eqep: QEPCTL:0x009e read
[   52.200222] eqep 48302180.eqep: irq:191, clk_rate:100000000
[   52.229209] kobject: '48304180.eqep' (d803cc18): kobject_add_internal: parent: '48304000.epwmss', set: 'devices'
[   52.229474] kobject: '48304180.eqep' (d803cc18): kobject_uevent_env
[   52.229496] kobject: '48304180.eqep' (d803cc18): fill_kobj_path: path = '/devices/platform/ocp/48304000.epwmss/48304180.eqep'
[   52.230685] eqep 48304180.eqep: ver. 1.0
[   52.231004] eqep 48304180.eqep: count_mode:0
[   52.231019] eqep 48304180.eqep: invert_qa:1
[   52.231030] eqep 48304180.eqep: invert_qb:1
[   52.231041] eqep 48304180.eqep: invert_qi:0
[   52.231052] eqep 48304180.eqep: invert_qs:0
[   52.231062] eqep 48304180.eqep: swap_inputs:0
[   52.231072] eqep 48304180.eqep: QDECCTL:0x0180
[   52.231081] eqep 48304180.eqep: QPOSINIT:0x00000000
[   52.231090] eqep 48304180.eqep: QPOSMAX:0xffffffff
[   52.231099] eqep 48304180.eqep: QPOSCNT:0x00000000
[   52.231109] eqep 48304180.eqep: omit_interrupt:0
[   52.231118] eqep 48304180.eqep: QEINT:0x0800
[   52.231127] eqep 48304180.eqep: QUPRD:0x05f5e100
[   52.231135] eqep 48304180.eqep: QEPCTL:0x009e write
[   52.231144] eqep 48304180.eqep: QEPCTL:0x009e read
[   52.231190] eqep 48304180.eqep: irq:193, clk_rate:100000000

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

*Any kernel folks have advice on how to troubleshoot this?*

The TI Sitara AM3358 SoC in the BeagleBone has a quaduture encoded pulse decoder peripheral named eQEP.  Nathaniel Lewis wrote a kernel driver for it:
https://github.com/Teknoman117/beaglebot/blob/master/encoders/patches/0001-tieqep-driver.patch

Robert C. Nelson has been including the patch in the BeagleBone kernel and it is working with 4.4:
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.4.y/patches/beaglebone/eqep

I'm attempting to use the eQEP driver with the 4.9.5-ti-r16:
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.9.y/patches/drivers/ti/eqep

I get a Segmentation Fault in eqep_get_position() when I read the sysfs position file:
# cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position

This readl() runs OK in eqep_probe() from drivers/misc/tieqep.c:
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.9.y/patches/drivers/ti/eqep#L401

Line 697: dev_info(&pdev->dev, "QPOSCNT:0x%08x\n", readl(eqep->mmio_base + QPOSCNT));

The output is seen ok in dmesg:
[   50.589737] eqep 48304180.eqep: eqep->mmio_base:fa304180
[   50.590080] eqep 48304180.eqep: QPOSCNT:0x00000000

However, the same readl() causes a seg fault in eqep_get_position():
https://github.com/RobertCNelson/ti-linux-kernel-dev/tree/ti-linux-4.9.y/patches/drivers/ti/eqep#L401

Line 401: position = readl(eqep->mmio_base + QPOSCNT);

from dmesg:
[ 1858.085381] DEBUG: tieqep.c: eqep_get_position: QPOSCNT=0
[ 1858.102133] DEBUG: tieqep.c: eqep_get_position: eqep->mmio_base=fa304180
[ 1858.108446] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa304184

These are the eqep enteries in /proc/iomem:
48300180-483001ff : /ocp/epwmss@48300000/eqep@0x48300180
48302180-483021ff : /ocp/epwmss@48302000/eqep@0x48302180
48304180-483041ff : /ocp/epwmss@48304000/eqep@0x48304180

I'm not sure what the difference is. Maybe the io memory mapping changed in between the probe and reading the sysfs file?

More details:
https://gist.github.com/pdp7/fe07082d23f2bfbc362c733a7b0aea72

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

Why ?

https://github.com/RobertCNelson/ti-linux-kernel-dev/blob/ti-linux-4.4.y/patches/beaglebone/eqep/0002-tieqep.c-devres-remove-devm_request_and_ioremap.patch

From 1ef85f0af49b6d03c72f2f3544abdfd26130b1dd Mon Sep 17 00:00:00 2001
From: Robert Nelson <robertcnelson@gmail.com>
Date: Fri, 5 Jun 2015 10:30:27 -0500
Subject: [PATCH 2/3] tieqep.c: devres: remove devm_request_and_ioremap()

Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
---
 drivers/misc/tieqep.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/misc/tieqep.c b/drivers/misc/tieqep.c
index e0ae946..d4698c2 100644
--- a/drivers/misc/tieqep.c
+++ b/drivers/misc/tieqep.c
@@ -504,9 +504,9 @@ static int eqep_probe(struct platform_device *pdev)
     }
 
     // Remap the eQEP controller memory into our own memory space
-    eqep->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
-    if (!eqep->mmio_base)
-        return  -EADDRNOTAVAIL;
+    eqep->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+    if (IS_ERR(eqep->mmio_base))
+        return PTR_ERR(eqep->mmio_base);
 
     // Store the platform device in our eQEP data structure for later usage
     eqep->pdev = pdev;
-- 
2.7.0.rc3

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

What kind of memory addresses are the ones shown by proc/ioports and proc/iomem?
https://superuser.com/questions/480451/what-kind-of-memory-addresses-are-the-ones-shown-by-proc-ioports-and-proc-iomem

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

root@beaglebone:~# dmesg
[  265.837587] DEBUG: tieqep.c: eqep_get_position: dev=d7e75410
[  265.843445] DEBUG: tieqep.c: eqep_get_position: attr=bf007098
[  265.849404] DEBUG: tieqep.c: eqep_get_position: buf=dc784000
[  265.855771] DEBUG: tieqep.c: eqep_get_position: call dev_get_drvdata(dev)
[  265.862752] DEBUG: tieqep.c: eqep_get_position: eqep=d7ebab10
[  265.868218] DEBUG: tieqep.c: eqep_get_position: TIEQEP_MODE_ABSOLUTE=0
[  265.874930] DEBUG: tieqep.c: eqep_get_position: TIEQEP_MODE_RELATIVE=1
[  265.881029] DEBUG: tieqep.c: eqep_get_position: QPOSCNT=0
[  265.886590] DEBUG: tieqep.c: eqep_get_position: QPOSLAT=24
[  265.891734] DEBUG: tieqep.c: eqep_get_position: eqep->op_mode=1
[  265.897810] DEBUG: tieqep.c: eqep_get_position: eqep->mmio_base=fa304180
[  265.904126] DEBUG: tieqep.c: eqep_get_position: eqep->pdev=d7e75400
[  265.910561] DEBUG: tieqep.c: eqep_get_position: r=d7efd8a0
[  265.915667] eqep 48304180.eqep: invalid resource
[  265.920431] DEBUG: tieqep.c: eqep_get_position: eqep_base=ffffffea
[  265.929426] DEBUG: tieqep.c: eqep_get_position: attempt readl(eqep_base)
[  265.936501] Unable to handle kernel paging request at virtual address ffffffea
[  265.945319] pgd = db1a0000
[  265.949161] [ffffffea] *pgd=9fde6861, *pte=00000000, *ppte=00000000
[  265.956326] Internal error: Oops: 37 [#1] PREEMPT SMP ARM
[  265.961785] Modules linked in: pwm_tiecap spi_omap2_mcspi omap_aes_driver crypto_engine omap_sham omap_rng rng_core evdev tps65217_charger uio_pdrv_genirq uio usb_f_mass_storage usb_f_acm u_serial usb_f_rndis u_ether libcomposite 8021q garp mrp stp llc spidev tieqep pwm_tiehrpwm
[  265.986969] CPU: 0 PID: 1966 Comm: cat Tainted: G        W       4.9.5-ti-r16 #4
[  265.994440] Hardware name: Generic AM33XX (Flattened Device Tree)
[  266.000591] task: db058e40 task.stack: d705e000
[  266.005194] PC is at eqep_get_position+0x13c/0x2a4 [tieqep]
[  266.010831] LR is at vprintk_emit+0x3c8/0x5e8
[  266.015232] pc : [<bf005614>]    lr : [<c01a4ebc>]    psr: 600f0013
sp : d705fe08  ip : d705fd50  fp : d705fe2c
[  266.026813] r10: 00000001  r9 : dc784000  r8 : d7efd8a0
[  266.032087] r7 : d7e75410  r6 : ffffffea  r5 : dc784000  r4 : d7ebab10
[  266.038671] r3 : 00040905  r2 : 00040905  r1 : c0c60e78  r0 : 0000003c
[  266.045259] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  266.052456] Control: 10c5387d  Table: 9b1a0019  DAC: 00000051
[  266.058255] Process cat (pid: 1966, stack limit = 0xd705e218)
[  266.064054] Stack: (0xd705fe08 to 0xd7060000)
[  266.068460] fe00:                   d7fffa80 bf007098 c0a61828 d7e75418 d7fffd80 dc784000
[  266.076723] fe20: d705fe44 d705fe30 c065ce60 bf0054e4 d7fffa80 00001000 d705fe6c d705fe48
[  266.084984] fe40: c037486c c065ce40 d7fffa80 00020000 db0d20c0 c0f04d4c 00000000 d705ff68
[  266.093246] fe60: d705fe7c d705fe70 c0373050 c03747e8 d705fedc d705fe80 c03121e4 c0373028
[  266.101508] fe80: c0f04d4c db0d20c0 d7fffab0 b6d26000 d705fe98 00020000 00000000 00000000
[  266.109769] fea0: 00000000 00040905 c0fce350 00040905 c994e6e0 d7fffd80 00020000 db0d20c0
[  266.118030] fec0: b6d26000 d705ff68 d705ff68 00020000 d705ff1c d705fee0 c0373f00 c0312018
[  266.126292] fee0: 00020000 00000000 db0d20c0 b6d26000 d705ff34 c0373dd4 00020000 db0d20c0
[  266.134554] ff00: b6d26000 d705ff68 00000000 00020000 d705ff34 d705ff20 c02e6020 c0373de0
[  266.142815] ff20: ffffe000 00020000 d705ff64 d705ff38 c02e6f74 c02e6004 000b6d25 c030b2f8
[  266.151076] ff40: c0f04d4c db0d20c0 00000000 00000000 db0d20c0 b6d26000 d705ffa4 d705ff68
[  266.159338] ff60: c02e81e4 c02e6ee4 00000000 00000000 c02b6dcc 00040905 00000022 00020000
[  266.167600] ff80: 00020000 b6d26000 00000003 c0109344 d705e000 00000000 00000000 d705ffa8
[  266.175860] ffa0: c0109180 c02e8194 00020000 00020000 00000003 b6d26000 00020000 000271c4
[  266.184122] ffc0: 00020000 00020000 b6d26000 00000003 7fffe000 00000000 00000000 00020000
[  266.192384] ffe0: 00000000 bec52a64 00013835 b6f5bea6 400f0030 00000003 00000000 00000000
[  266.200682] [<bf005614>] (eqep_get_position [tieqep]) from [<c065ce60>] (dev_attr_show+0x2c/0x58)
[  266.209663] [<c065ce60>] (dev_attr_show) from [<c037486c>] (sysfs_kf_seq_show+0x90/0x100)
[  266.217931] [<c037486c>] (sysfs_kf_seq_show) from [<c0373050>] (kernfs_seq_show+0x34/0x38)
[  266.226285] [<c0373050>] (kernfs_seq_show) from [<c03121e4>] (seq_read+0x1d8/0x56c)
[  266.234024] [<c03121e4>] (seq_read) from [<c0373f00>] (kernfs_fop_read+0x12c/0x1dc)
[  266.241766] [<c0373f00>] (kernfs_fop_read) from [<c02e6020>] (__vfs_read+0x28/0x48)
[  266.249506] [<c02e6020>] (__vfs_read) from [<c02e6f74>] (vfs_read+0x9c/0x164)
[  266.256710] [<c02e6f74>] (vfs_read) from [<c02e81e4>] (SyS_read+0x5c/0xbc)
[  266.263659] [<c02e81e4>] (SyS_read) from [<c0109180>] (ret_fast_syscall+0x0/0x3c)
[  266.271225] Code: eb49bae8 e3060680 e34b0f00 eb49bae5 (e5961000) 
[  266.288267] ---[ end trace 9dc63d83b97d0077 ]---
root@beaglebone:~# 

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

root@beaglebone:~# dmesg |grep r=
[   50.862712] eqep 48300180.eqep: r=platform_get_resource(pdev, IORESOURCE_MEM, 0)=d7e86340
[   50.963868] eqep 48302180.eqep: r=platform_get_resource(pdev, IORESOURCE_MEM, 0)=d7ee8d00
[   51.066747] eqep 48304180.eqep: r=platform_get_resource(pdev, IORESOURCE_MEM, 0)=d7ecc440
[  328.727526] DEBUG: tieqep.c: eqep_get_position: attr=bf007098
[  328.794325] DEBUG: tieqep.c: eqep_get_position: r=d7ecc460
root@beaglebone:~# 

@pdp7
Copy link
Author

pdp7 commented Jan 28, 2017

https://plus.google.com/u/0/+DrewFustini/posts/MYfYUyQvv7W

Michael Welling's profile photo
Michael Welling
+2
This external abort fault is probably caused by the clock being dynamically disabled by runtime suspend. pm_runtime_get_sync is missing somewhere.
13h
Felipe Balbi's profile photo
Felipe Balbi
+1
Looking at the diff, it works on 4.4 out of sheer luck. There's nothing guaranteeing clock won't be gated. Enable pm runtime and call pm runtime get sync as +Michael Welling said

@pdp7
Copy link
Author

pdp7 commented Jan 29, 2017

http://elinux.org/BeagleBoardPWM

When you run your code you may encounter the following error:

root@beagleboard:# ./pwm-demo
0
Bus error
root@beagleboard:
# dmesg | tail -1
[ 174.893035] Unhandled fault: external abort on non-linefetch (0x1818) at 0x4001e024
This is caused because the library does not enable the PWM clocks and you are not allowed to access them until this is done. In order to fix this you need to recompile your kernel with the option CONFIG_OMAP_RESET_CLOCKS disabled. More information can be found in this thread: http://groups.google.com/group/beagleboard/browse_thread/thread/ee42e5c59edf83cd/67be50968de6a9f2?lnk=gst&q=guint8#67be50968de6a9f2

or see the note above at: http://elinux.org/BeagleBoardPWM#OMAP_Mux_Configuration

@pdp7
Copy link
Author

pdp7 commented Jan 29, 2017

You may have device mapping setup properly. A common case is where the clocks for a peripheral are not enabled and the device does not respond to a bus request; especially external abort type messages maybe due to a missing clk_prepare_enable(). – artless noise Nov 21 '13 at 18:25

https://stackoverflow.com/questions/15889483/what-do-these-kernel-panic-errors-mean#comment29997758_15890328

@pdp7
Copy link
Author

pdp7 commented Jan 29, 2017

You need to make sure that the appropriate McSPI functional (CM_FCLKEN1_CORE) and interface (CM_ICLKEN1_CORE) clocks are enabled before reading the McSPI registers.

https://e2e.ti.com/support/embedded/linux/f/354/t/49197

@pdp7
Copy link
Author

pdp7 commented Jan 29, 2017

Because the PWM pins are not set as such by default, the OMAP's mux must be configured to expose them before they can be used. See BeagleBoardPinMux for more details on this procedure. The short version is to add the following lines to the definition of board_mux[] in arch/arm/mach-omap2/board-omap3beagle.c (this has been tested with the 2.6.33 OMAP branch of the kernel).

OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE2|OMAP_PIN_OUTPUT), /* GPT9_PWMEVT, ball AB26, ex pin 4 /
OMAP3_MUX(UART2_TX, OMAP_MUX_MODE2|OMAP_PIN_OUTPUT), /
GPT11_PWMEVT, ball AA25, ex pin 6 /
OMAP3_MUX(UART2_RTS, OMAP_MUX_MODE2|OMAP_PIN_OUTPUT), /
GTP10_PWMEVT, ball AB25, ex pin 10 */
Obviously these lines should precede the line terminating the array. This will likely be in a block conditional on CONFIG_OMAP_MUX, so you need to have the CONFIG_OMAP_MUX option set in your kernel config.

Note: Setting the kernel config option CONFIG_OMAP_RESET_CLOCKS to yes [| may cause problems].

http://elinux.org/BeagleBoardPWM#OMAP_Mux_Configuration

@pdp7
Copy link
Author

pdp7 commented Jan 30, 2017

CM_PER_L4LS_CLKSTCTRL

I2C with the Beaglebone Black

https://tekuconcept.blogspot.com/2014/05/i2c-with-beaglebone-black.html

REGISTERS
To access i2c registers, the interface clock [ICLK] first needs to be un-gated. This can be done through the Power, Reset, and Clock Management [PRCM] module registers: CM_PER_L4LS_CLKSTCTRL & CM_PER_I2C_CLKCTRL. For this demonstration, the code from the git repository BoneMemory is used - load the shell script with "source script.sh" command.

# Enable I2C2 ICLK and FCLK - otherwise 'Bus Error'
writem 0x44E00000  0 0 # CM_PER_L4LS_CLKSTCTRL.MODULCTRL = 0
writem 0x44E00000 50 2 # CM_PER_I2C2_CLKCTRL = 2

# Prepare bus data and begin
writem 0x4819C000 98 1 # I2C_CNT  = 1
writem 0x4819C000 9C F # I2C_DATA = 0x0F
writem 0x4819C000 A4 8C03 # EN/MASTER/TX/START/STOP

See Pg 3715 of the Technical Reference Manual for a detailed approach to reading and writing via registers.

@pdp7
Copy link
Author

pdp7 commented Jan 30, 2017

CM_PER_L4LS_CLKSTCTRL

root@beaglebone:~# find /sys |grep l4ls
/sys/kernel/debug/clk/l4ls_gclk
/sys/kernel/debug/clk/l4ls_gclk/clk_notifier_count
/sys/kernel/debug/clk/l4ls_gclk/clk_enable_count
/sys/kernel/debug/clk/l4ls_gclk/clk_prepare_count
/sys/kernel/debug/clk/l4ls_gclk/clk_flags
/sys/kernel/debug/clk/l4ls_gclk/clk_phase
/sys/kernel/debug/clk/l4ls_gclk/clk_accuracy
/sys/kernel/debug/clk/l4ls_gclk/clk_rate
root@beaglebone:~# find /sys/ -type f |grep l4ls |xargs more
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_notifier_count
::::::::::::::
0
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_enable_count
::::::::::::::
36
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_prepare_count
::::::::::::::
44
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_flags
::::::::::::::
0x00000020
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_phase
::::::::::::::
0
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_accuracy
::::::::::::::
0
::::::::::::::
/sys/kernel/debug/clk/l4ls_gclk/clk_rate
::::::::::::::
100000000
::::::::::::::
/sys/firmware/devicetree/base/__symbols__/l4ls_gclk
::::::::::::::
/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk
::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/compatible
::::::::::::::
fixed-factor-clock
::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/clocks
::::::::::::::

::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/clock-mult
::::::::::::::

::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/#clock-cells
::::::::::::::

::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/phandle
::::::::::::::

::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/linux,phandle
::::::::::::::

::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/clock-div
::::::::::::::

::::::::::::::
/sys/firmware/devicetree/base/ocp/l4_wkup@44c00000/prcm@200000/clocks/l4ls_gclk/name
::::::::::::::
l4ls_gclk

@pdp7
Copy link
Author

pdp7 commented Jan 30, 2017

@pdp7
Copy link
Author

pdp7 commented Jan 30, 2017

9/23/12
Hi Ethan,
I got below code sometime back in this group itself. I didn't find that link now. Find the link below, c code for enable PWM clock in beaglebone. It works fine for me.
http://db.tt/9V3Ia9Rt

@pdp7
Copy link
Author

pdp7 commented Jan 30, 2017

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
 
#define CM_PER_REG_START 0x44e00000
#define CM_PER_REG_LENGTH 1024
#define CM_PER_EPWMSS0_CLKCTRL_OFFSET 0xd4
#define CM_PER_EPWMSS1_CLKCTRL_OFFSET 0xcc
#define CM_PER_EPWMSS2_CLKCTRL_OFFSET 0xd8
 
#define PWM_CLOCK_ENABLE 0x2
#define PWM_CLOCK_DISABLE 0x0
 
#define PWM_LIST_MAX 3
 
int PWM_OFFSETS[PWM_LIST_MAX] = 
{
  CM_PER_EPWMSS0_CLKCTRL_OFFSET / sizeof (uint32_t), /*53*/
  CM_PER_EPWMSS1_CLKCTRL_OFFSET / sizeof (uint32_t), /*51*/
  CM_PER_EPWMSS2_CLKCTRL_OFFSET / sizeof (uint32_t)  /*54*/
};
 
void print_usage (const char *message)
{
  if (message)
    printf ("%s\n", message);
 
  printf ("pwm_clock <-e | -d> <PWM [PWM]>\n\n");
}
 
int main (int argc, char **argv)
{
  int i;
  int *cur_list = NULL;
  int *cur_list_index = NULL;
  int enable_list[PWM_LIST_MAX];
  int enable_list_index = 0;
  int disable_list[PWM_LIST_MAX];
  int disable_list_index = 0;
  int dev_mem_fd;
  volatile uint32_t *cm_per_regs;
 
  for (i = 0; i < PWM_LIST_MAX; ++i)
    {
        enable_list[i] = -1;
        disable_list[i] = -1;
    }
 
  for (i = 1; i < argc; ++i)
    {
        if (strncmp (argv[i], "-e", 2) == 0) 
        {
            cur_list = enable_list;
            cur_list_index = &enable_list_index;
            }
 
        else if (strncmp (argv[i], "-d", 2) == 0) 
        {
            cur_list = disable_list;
            cur_list_index = &disable_list_index;
            }
        else
        {
            if (!cur_list) 
        {
            print_usage (0);
            return 1;
            }
 
        if (*cur_list_index >= PWM_LIST_MAX) 
        {
            print_usage ("Too many PWM's specified for an option");
            return 1;
        }
 
      cur_list[*cur_list_index] = atoi (argv[i]);
      ++*cur_list_index;
    }
  }
 
  dev_mem_fd = open ("/dev/mem", O_RDWR);
   
  if (dev_mem_fd == -1) 
    {
        perror ("open failed");
        return 1;
    }
 
  cm_per_regs = (volatile uint32_t *)mmap (NULL, CM_PER_REG_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, CM_PER_REG_START);
         
  if (cm_per_regs == (volatile uint32_t *)MAP_FAILED) 
    {
        perror ("mmap failed");
        close (dev_mem_fd);
        return 1;
    }
 
  for (i = 0; i < PWM_LIST_MAX && enable_list[i] != -1; ++i) 
    {
            if (enable_list[i] < 0 || enable_list[i] >= PWM_LIST_MAX) 
        {
            printf ("Invalid PWM specified, %d\n", enable_list[i]);
            goto out;
            }
 
        printf ("Enabling PWM %d\n", enable_list[i]);
        cm_per_regs[PWM_OFFSETS[enable_list[i]]] = PWM_CLOCK_ENABLE;
    }
 
  for (i = 0; i < PWM_LIST_MAX && disable_list[i] != -1; ++i) 
    {
        if (disable_list[i] < 0 || disable_list[i] >= PWM_LIST_MAX) 
        {
            printf ("Invalid PWM specified, %d\n", disable_list[i]);
            goto out;
            }
 
        printf ("Disabling PWM %d\n", disable_list[i]);
        cm_per_regs[PWM_OFFSETS[disable_list[i]]] = PWM_CLOCK_DISABLE;
    }
 
out:
  munmap ((void *)cm_per_regs, CM_PER_REG_LENGTH);
  close (dev_mem_fd);
 
  return 0;
}```

@pdp7
Copy link
Author

pdp7 commented Jan 30, 2017

The original tieqep driver had this code to enable the clock to the eQEP unit:
https://github.com/Teknoman117/beaglebot/blob/master/encoders/patches/0001-tieqep-driver.patch#L721

// Enable the clock to the eQEP unit
status = pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EQEPCLK_EN);

// If we failed to enable the clocks, fail out
if (!(status & PWMSS_EQEPCLK_EN_ACK))
{
    dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
    ret = -EINVAL;
    goto pwmss_clk_failure;
}

The function pwmss_submodule_state_change() appears to have been removed by this commit:

commit cc37655e6bbf83ded1e4d1d7ffd977786a845a67
Author: Cooper Jr., Franklin <fcooper@ti.com>
Date:   Mon Mar 7 13:33:56 2016 -0600

    pwm: pwm-ti*: Remove support for local clock gating
    
    The PWMSS local clock gating registers have no real purpose on OMAP ARM
    devices. These registers were left over registers from DSP IP where the
    PRCM doesn't exist. There is a silicon bug where gating and ungating clocks
    don't function properly. TRMs will be update to indicate that these
    registers shouldn't be touched.
    
    Therefore, all code that accesses the PWMSS_CLKCONFIG or PWMSS_CLKSTATUS
    will be removed by this patch with zero loss of functionality by the ECAP
    and EPWM drivers.
    
    Signed-off-by: Franklin S Cooper Jr <fcooper@ti.com>
    Signed-off-by: Thierry Reding <thierry.reding@gmail.com>

@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

@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