omap_timer omap_timer.8: omap2_dm_timer_set_src: clk_set_parent() to sys_ck FAILED #3

Open
erazor83 opened this Issue Dec 10, 2011 · 25 comments

Projects

None yet

5 participants

@erazor83

Hi,

I compiled the module against a git tree of www.sakoman.com (
http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=shortlog;h=refs/heads/omap-3.2 ) and tried to use it on my gumstix overo board.

When i try to load the module this error occurs in my dmesg:
omap_timer omap_timer.8: omap2_dm_timer_set_src: clk_set_parent() to sys_ck FAILED

CONFIG_OMAP_RESET_CLOCKS is not set in my kernel-config.

Does the module work with the 3er series of the kernel? Do you have any hints for me whats exactly the problem is?

Thanks so far.

Kind regards,
Alex

@scottellis
Owner

Hi Alex,

I think 2.6.39 was the last version I tested that driver.

I'll take a look at 3.2.

Thanks for the report.

Scott

On 12/10/11, Alexander Krause
reply@reply.github.com
wrote:

Hi,

I compiled the module against a git tree of www.sakoman.com (
http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=shortlog;h=refs/heads/omap-3.2
) and tried to use it on my gumstix overo board.

When i try to load the module this error occurs in my dmesg:
omap_timer omap_timer.8: omap2_dm_timer_set_src: clk_set_parent() to sys_ck
FAILED

CONFIG_OMAP_RESET_CLOCKS is not set in my kernel-config.

Does the module work with the 3er series of the kernel? Do you have any
hints for me whats exactly the problem is?

Thanks so far.

Kind regards,
Alex


Reply to this email directly or view it on GitHub:
#3

@erazor83

Hi Scott,

it's not that important but i thought it makes sense to let you know.

Kind regards and a happy new one!

On 17:34:10 11/12/11 Scott Ellis reply@reply.github.com wrote:

Hi Alex,

I think 2.6.39 was the last version I tested that driver.

I'll take a look at 3.2.

Thanks for the report.

Scott

On 12/10/11, Alexander Krause
reply@reply.github.com
wrote:

Hi,

I compiled the module against a git tree of www.sakoman.com (
http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=sh
ortlog;h=refs/heads/omap-3.2
) and tried to use it on my gumstix overo board.

When i try to load the module this error occurs in my dmesg:
omap_timer omap_timer.8: omap2_dm_timer_set_src: clk_set_parent()
to sys_ck FAILED

CONFIG_OMAP_RESET_CLOCKS is not set in my kernel-config.

Does the module work with the 3er series of the kernel? Do you
have any hints for me whats exactly the problem is?

Thanks so far.

Kind regards,
Alex


Reply to this email directly or view it on GitHub:
#3


Reply to this email directly or view it on GitHub:
#3 (comment)

@scottellis
Owner

Hi Alex,

I've been pretty busy.

Starting a new company, using another processor for our boards, so not
doing much Gumstix/OMAP3 stuff.

When 3.2 gets official for the Gumstix or Beagleboard I'll take a
look. I'm guessing it's some new PM change that's causing problems.

Scott

On 12/29/11, Alexander Krause
reply@reply.github.com
wrote:

Hi Scott,

it's not that important but i thought it makes sense to let you know.

Kind regards and a happy new one!

On 17:34:10 11/12/11 Scott Ellis reply@reply.github.com wrote:

Hi Alex,

I think 2.6.39 was the last version I tested that driver.

I'll take a look at 3.2.

Thanks for the report.

Scott

On 12/10/11, Alexander Krause
reply@reply.github.com
wrote:

Hi,

I compiled the module against a git tree of www.sakoman.com (
http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=sh
ortlog;h=refs/heads/omap-3.2
) and tried to use it on my gumstix overo board.

When i try to load the module this error occurs in my dmesg:
omap_timer omap_timer.8: omap2_dm_timer_set_src: clk_set_parent()
to sys_ck FAILED

CONFIG_OMAP_RESET_CLOCKS is not set in my kernel-config.

Does the module work with the 3er series of the kernel? Do you
have any hints for me whats exactly the problem is?

Thanks so far.

Kind regards,
Alex


Reply to this email directly or view it on GitHub:
#3


Reply to this email directly or view it on GitHub:
#3 (comment)


Reply to this email directly or view it on GitHub:
#3 (comment)

@milosoftware

I've been banging my head at the same problem for weeks, any news?

@scottellis
Owner

I did just setup a 3.2 kernel Gumstix system for a customer yesterday.

In the next day or so I'll try to take a look.

On 5/22/12, Mike Looijmans
reply@reply.github.com
wrote:

I've been banging my head at the same problem for weeks, any news?


Reply to this email directly or view it on GitHub:
#3 (comment)

@scottellis
Owner

There is a new [3.2] branch that appears to fix the issue of not working at all.

It was a PM related change that caused the problem. Timers must now be enabled before you can set any of the timer registers. New behavior. Easy fix.

There is another new problem though. You can no longer unload and then reload the pwm driver. It won't load the second time.

The error is related to changing the clock source, but it is internal to the omap dmtimer.c code. It is not the pwm driver trying to change the clock source. That is attempted later.

The error happens in arch/arm/plat-omap/dmtimer.c - omap_dm_timer_request_specific() -> omap_dm_timer_prepare().

I will try to find a solution.

As long as you are only loading the driver once, I think it will work okay.

@milosoftware

If I understand you correctly, this only fixes the driver not working at all, but it does NOT fix the problem with the clock source?

The "enable" thing is something I tried, but i figured the syntax would be something like calling omap_dm_timer_enable(..) when we're going to use it, and omap_dm_timer_disable(..) when we're done with it, so basically in the open and close of the driver.

Your patch suggests something entirely different, is it so that one has to surround every access to the timer functions with enable..disable calls? I really don't understand why your fix would work, it only puts that around one function that isn't even critical.

Is there any place where I could find some information on the dmtimer interface? How did you find it? Or is the only way to discover this just looking at the source?

From where i'm standing now, the easiest to do would be to just eliminate the timers I want to use from the kernel, and just bitbang the registers myself. At least that's properly documented...

@scottellis
Owner

Not exactly.

Direct calls to omap_dm_timer_write() require the timer to be enabled
first. I went ahead and removed my call to that function since as you
point out, it wasn't really necessary. Who cares about the initial
TLDR value.

Wrapper calls like omap_dm_timer_set_match() or
omap_dm_timer_set_load() for registers that you really care about have
code in them to take care of the enable/disable for you.

So that fixes the problem of loading and using the driver. If you only
load it once everything is fine.

The second problem still needs to be worked out.

Take a look at dmtimer.c - omap_dm_timer_request_specific()

It calls omap_dm_timer_set_source() then

arch/arm/mach-omap2/timer.c - omap2_dm_timer_set_src()

arch/arm/plat-omap/clock.c - clk_set_parent()

It looks like the call to clk_set_parent() is failing even if the same
parent clock is being chosen. i.e. even if the parent clock is never
changed between driver loads.

The error number gets swallowed so I need to put some tracing in there
to find out exactly where the problem is.

I removed all calls to omap_dm_timer_set_source() in pwm.c for testing
and I put in enough printk's to know the error happens when calling
omap_dm_timer_request_specific()

The only other data point I have right now is that there is no problem
as long as the timer was not started. So for example you can load
pwm.ko, remove it and add it again without having started a timer, the
driver works fine.

If you load the pwm driver and start timer 8, stop it and unload the
driver. Then when you load it a second time it will complain about not
being able to change the source clock for timer 8.

Or if you loaded the pwm driver, started timer 9, unloaded the driver.
When you load the driver again, timer 8 is fine, but timer 9 will now
complain. My driver aborts the load if any requested timer fails to
load.

I didn't know about the dmtimer interface when I wrote the first
version of the pwm driver a few years ago. I went directly at
the registers using the TRM for reference.

Later kernels started taking more control of the timers and I kind of
stumbled on that dmtimer code trying to figure out how to enable the
source clocks for the timers. It's mostly just small wrappers around
the stuff any driver has to do to fiddle the timer regs.

There was still not enough in dmtimer.c to use the timers for capture.
At least not the last time I needed to do that. I should probably post
that code with the mods to dmtimer.c somewhere.

I don't know of any documentation for that dmtimer code.

Anyway, that's where I'm at. I have some other things I have to work
on right now, but I'll try to get back to this later in the week.

If you find something I'd be happy to hear about it.

On 5/23/12, Mike Looijmans
reply@reply.github.com
wrote:

If I understand you correctly, this only fixes the driver not working at
all, but it does NOT fix the problem with the clock source?

The "enable" thing is something I tried, but i figured the syntax would be
something like calling omap_dm_timer_enable(..) when we're going to use it,
and omap_dm_timer_disable(..) when we're done with it, so basically in the
open and close of the driver.

Your patch suggests something entirely different, is it so that one has to
surround every access to the timer functions with enable..disable calls? I
really don't understand why your fix would work, it only puts that around
one function that isn't even critical.

Is there any place where I could find some information on the dmtimer
interface? How did you find it? Or is the only way to discover this just
looking at the source?

From where i'm standing now, the easiest to do would be to just eliminate
the timers I want to use from the kernel, and just bitbang the registers
myself. At least that's properly documented...


Reply to this email directly or view it on GitHub:
#3 (comment)

@KaliberImaging

I don't know if this is a different side of the same coin, a new problem or my problem. Once I insmod pwm.ko and I rmmod it, I get:

insmod: error inserting 'pwm.ko': -1 Operation not permitted

An additional factor is persistence, which may be my problem. The system does not recognize 'pwm.ko' on reboot. upon reboot, I get this:

desktop:/root# insmod pwm.ko timers=9,10,11
insmod: can't read 'pwm.ko': No such file or directory

I can readily compile it, only if I remove the artifacts from the last make:

desktop:/root/Documents/pwm# make
make -C /lib/modules/3.2.0-29-omap/build M=/root/Documents/pwm modules
make[1]: Entering directory /usr/src/linux-headers-3.2.0-29-omap' CC [M] /root/Documents/pwm/pwm.o Building modules, stage 2. MODPOST 1 modules CC /root/Documents/pwm/pwm.mod.o LD [M] /root/Documents/pwm/pwm.ko make[1]: Leaving directory/usr/src/linux-headers-3.2.0-29-omap'
desktop:/root/Documents/pwm# insmod pwm.ko timers=9,10,11
desktop:/root/Documents/pwm# cat /dev/pwm9
0
desktop:/root/Documents/pwm# echo 50 > /dev/pwm9

When I remove the module and try to re-install it, I get this:

desktop:/root/Documents/pwm# rmmod pwm
desktop:/root/Documents/pwm# insmod pwm.ko timers=9,10,11
insmod: error inserting 'pwm.ko': -1 Operation not permitted

I am native compiling and the make file is:

obj-m := pwm.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean

uname -r tells me that I am using 3.2.0-29-omap

The only pwm.ko produced today is in the same directory that I make it. If I read the makefile correctly, it is supposed to put it in /lib/modules/3.2.0-29-omap/build and it does not. It also is supposed to clean up after compiling. I believe that is the persistence problem and I will work on that separately, but if you see an obvious error, I'd appreciate it.

The system is Ubuntu 12.04 with Unity disabled and XFCE4 installed. Unity requires a minimum 1GHz proc and 1GB of memory and neither is particularly compatible with a BeagleBoardXM. The XFCE4 only requires 300 MHz and 200MB. For actual operations, I will run it headless from the shell (it boots to shell and I run the desktop).

@KaliberImaging

By the way, I don't initialize PWM8 because it kills the USB.

@scottellis
Owner

Sounds like you are seeing exactly the symptoms described in those earlier posts.

You cannot reload the pwm module if you used a timer when it was loaded. I suspect you are not trying your insmod commands from a console otherwise you would also see the reason the insmod failed instead of only the generic failure message.

insmod: error inserting 'pwm.ko': -1 Operation not permitted

Check your syslog for the real failure reason. I'm pretty sure it will be an error about not being able to reparent the timer src clock. Either that or try loading from a console session.

Your insmod error on boot comes from the fact that insmod requires a full-path to the driver.

desktop:/root# insmod pwm.ko timers=9,10,11
insmod: can't read 'pwm.ko': No such file or directory

Provide the full-path to pwm.ko. The first insmod of the driver should always work.

The warning to BeagleBoard users about timer 8 messing with USB has been in the README for a long time.
It's down in the notes near the bottom.

@KaliberImaging

Thanks for your prompt answer. I was afraid it was the same problem. They appear to not have fixed the 3.2 kernel.

I tried installing a newer kernel but none of them want to boot. The latter distros mess with the boot.scr and uEnv.txt doesn't work for me. I don't feel like messing with the uEnv.txt/boot.scr right now. So, I'm installing a Ubuntu 11.10 distro that has the 3.0 kernel. I looked at Linaro and they stopped updating the BeagleBoard distro because they couldn't get it to boot. I will figure out how to fix it later. I haven't worked on UNIX since I was using microbus and a 6800. So, the functions are little foggy.

Thanks for the heads up on the full path. I had read some place else that I should do a make modules-install. I had tried that with another LKM, but it said that make didn't have that command. I'll work on that.

@scottellis
Owner

Why do you need to reload the pwm driver?

I haven't had any problems using it when I load it once at boot. The
problem is more of a hassle during development. Not really a problem
for me in production.

The pwm module is built out-of-tree unless you've modified it.
modules-install won't help you. That's for in-tree modules.

You should modify your startup script to use the full path to the
pwm.ko when using insmod.

At least that's what I do.

On 8/1/12, KaliberImaging
reply@reply.github.com
wrote:

Thanks for your prompt answer. I was afraid it was the same problem. They
appear to not have fixed the 3.2 kernel.

I tried installing a newer kernel but none of them want to boot. The latter
distros mess with the boot.scr and uEnv.txt doesn't work for me. I don't
feel like messing with the uEnv.txt/boot.scr right now. So, I'm installing
a Ubuntu 11.10 distro that has the 3.0 kernel. I looked at Linaro and they
stopped updating the BeagleBoard distro because they couldn't get it to
boot. I will figure out how to fix it later. I haven't worked on UNIX
since I was using microbus and a 6800. So, the functions are little foggy.

Thanks for the heads up on the full path. I had read some place else that I
should do a make modules-install. I had tried that with another LKM, but it
said that make didn't have that command. I'll work on that.


Reply to this email directly or view it on GitHub:
#3 (comment)

@KaliberImaging

Thanks Scott.
I tried a couple of distros and found various problems...like no compatible header files. I settled on Linaro 1203
which has kernel 3.1.1-21. When I installed pwm, it worked fine. When I tried to re-insert it, it froze the
machine. It accepted the insmod, though. I've moved forward a little.

I can send you the whole syslog for this, if you wish. There seems to be a series hub 1-2:1.0: port 2 events associated with the initial insmod and hub 1.0:1-0: port 2 with the ones resulting in a freeze. I'm going to attempt a recompile by removing all references to pwm8.

Thanks
Ralph

@KaliberImaging

I commented out the references to timer 8 and pwm8 and changed the 4 timers to 3. It inserted and removed the pwm module fine. I rmmod pwm and it shut down OK. I insmod ed it again and it still had the random tripping. I decided to reboot and forgot to rmmod. After reboot, it came back with the message
Timer 9 specified more than once
insmod: error inserting '/workspace/pwm/pwm.ko' : -1 operation not permitted

I tried rmmod and it told me that pwm was not inserted. A clean install got the same results. My guess is that the bug extended to 3.1.1-21. I will be looking to a 3.0 that I can use. There were some changes from 2.6 that creates problems for me if I go back that far.

@scottellis
Owner

On 8/3/12, KaliberImaging
reply@reply.github.com
wrote:

This is more my problem than yours, but you may be the most helpful
advisor.

I commented out the references to timer 8 and pwm8 and changed the 4 timers
to 3. It inserted and removed the pwm module fine.

You could also just pass an argument to the driver when calling insmod

insmod pwm.ko timers=9,10,11

This way the driver will not touch timer 8. Instructions are in the README.

I made an error on echo 50>pwm9 instead of 50>/dev/pwm9. That created a
little havoc on all timers tripping level at random.

"echo 50 > pwm9" shouldn't hurt anything. If you ran this from the
/dev dir then it
would be a normal command to the driver. If you ran it anywhere else,
it would not
affect the driver, it would just create a new file called 'pwm9'.

I rmmod pwm and it
shut down OK. I insmod ed it again and it still had the random tripping. I
decided to reboot and forgot to rmmod. After reboot, it came back with the
message
Timer 9 specified more than once
insmod: error inserting '/workspace/pwm/pwm.ko' : -1 operation

I tried rmmod and it told me that pwm was not inserted. Still, it is obvious
a fragment of pwm is stored someplace. I looked at all the folders
associated with the modules and all the usual suspects.

Do you know where the system stores the previous instance?

Nothing that I know of. Rebooting always works for me.

@svolpe
svolpe commented Jul 16, 2013

I'm using your latest code and I still get:
omap_timer omap_timer.10: omap2_dm_timer_set_src: clk_set_parent() to sys_ck FAILED
Error: could not insert module pwm.ko: Operation not permitted

My kernel version is as follows: 3.2.28
Any suggestions what could be going wrong?

@svolpe
svolpe commented Jul 16, 2013

I removed the following lines of code and now it works. So for some reason the omap_dm_timer_set_source does not work. Although the PWM seems to work fine with out that call.
// if (omap_dm_timer_set_source(pwm_dev[i].timer,
// OMAP_TIMER_SRC_SYS_CLK))
// goto timer_init_fail;

@scottellis
Owner

I'm not sure what to suggest.

I'm using the pwm driver on several projects with a 3.2 kernel on a Gumstix Overo without any problems. The kernel comes from the gumstix/meta-gumstix repo on Github.

Without that omap_dm_timer_set_source() call, the timer is likely using a 32K source timer and not the 13MHz sys timer. That might not be a problem for you. It just means a coarser resolution and less range for the frequency.

It's still an outstanding problem that you cannot reload the driver on a running system if you activated any of the pwm timers. Then you will get the error that you are seeing.

That's usually only a problem (for me mostly) during development. I have looked at the problem, but the solution isn't obvious. My dev systems reboot under 10 seconds so it's not been inconvenient enough to force me to fix.

My production systems only load the driver once at boot so it's never a problem there.

@svolpe
svolpe commented Jul 18, 2013

Scott,
Thanks for the quick response.

I've traced it down to the following code inside of clk_set_parent():
if (clk->usecount == 0) {
ret = arch_clock->clk_set_parent(clk, parent);
if (ret == 0)
propagate_rate(clk);
} else{
ret = -EBUSY;

Where clk->usercount is NOT equal to zero so clk_set_parent() returns -EBUSY. I will keep digging into usercount, any insight on it that you might have would also be helpful.

@scottellis
Owner

So I'm clear, you get an error the first time you load the driver?

@svolpe
svolpe commented Jul 18, 2013

Yes, the first time I load the driver.

@svolpe
svolpe commented Jul 18, 2013

Scott,
I just fixed my problem and the problem of removing/adding back in the module. Not sure if this is clean or not (pretty sure it probably is not as I just hacked it) so hopefully you can give me insight on a better approach.

The problem is to set the timer (clk) source there must not be anyone using the clk (as per my post above). Your PWM code actually registers the timer (clk) somewhere early on (not sure where) so it is actually using it in my kernel therefore when the code goes to set the src it punts out because usecount is equal to 1. I fixed this part of the problem by just issuing a clock disable/enable around the code were the src is being set as clk_disable() decrements usecount and disables the clk if no one is using it and clk_enable() increments usecount and enables the clk.

//ADDED CODE
fclk = omap_dm_timer_get_fclk(pwm_dev[i].timer); //Moved up from below!!
clk_disable(fclk);
//END ADDED CODE
if (omap_dm_timer_set_source(pwm_dev[i].timer,
OMAP_TIMER_SRC_SYS_CLK))
goto timer_init_fail;
clk_enable(fclk);

Next, the module removing reinserting problem seems to be the same issue. The clk is never being disabled (usecount decremented) when the module is removed so the next time it can't set the source and the disable/enable I have in place does not work since the usecount is now 2 instead of 1 and since clk_disable only decrements by 1 usecount is not 0. I just added a clk_disable to the pwm_timer_cleanup() function:

static void pwm_timer_cleanup(void)
{
int i;
struct clk *fclk;

    for (i = 0; i < num_timers; i++) {
            pwm_off(&pwm_dev[i]);

//ADDED CODE
fclk = omap_dm_timer_get_fclk(pwm_dev[i].timer);
clk_disable(fclk);
//END ADDED CODE

            if (pwm_dev[i].timer) {
                    omap_dm_timer_free(pwm_dev[i].timer);
                    pwm_dev[i].timer = NULL;
                    if (irq_mode)
                            free_irq(pwm_dev[i].irq, &pwm_dev[i]);
            }

            pwm_restore_mux(&pwm_dev[i]);

    }

}

@scottellis
Owner

The use part of your explanation makes sense and I'll experiment with adding
a clk_disable() to the driver cleanup.

I don't understand why you can't use the driver on first load though and
I can.

In your kernel config, what's the value of CONFIG_OMAP_RESET_CLOCKS ?
Mine is set to yes. That might be it.

There are no other functions that touch the timers before the drivers
pwm_timer_init()

pwm_timer_init()
---> omap_dm_timer_request_specific()
---> omap_dm_timer_set_pwm()
---> omap_dm_timer_set_source()

If you look at omap_dm_timer_request_specific() it does the following

omap_dm_timer_request_specific()
---> omap_dm_timer_prepare()
------> omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ)

which is the source clock we are trying to override.

We can't do the set_source() call before the request() call because
we need a timer pointer.

You could try putting the set_source() call before the set_pwm() call
though I don't think that's going to fix anything or my system would
be broken as well.

On 07/18/2013 10:43 AM, Shane Volpe wrote:

Scott,
I just fixed my problem and the problem of removing/adding back in the
module. Not sure if this is clean or not (pretty sure it probably is
not as I just hacked it) so hopefully you can give me insight on a
better approach.

The problem is to set the timer (clk) source there must not be anyone
using the clk (as per my post above). Your PWM code actually registers
the timer (clk) somewhere early on (not sure where) so it is actually
using it in my kernel therefore when the code goes to set the src it
punts out because usecount is equal to 1. I fixed this part of the
problem by just issuing a clock disable/enable around the code were
the src is being set as clk_disable() decrements usecount and disables
the clk if no one is using it and clk_enable() increments usecount and
enables the clk.

//ADDED CODE
fclk = omap_dm_timer_get_fclk(pwm_dev[i].timer); //Moved up from below!!
clk_disable(fclk);
//END ADDED CODE
if (omap_dm_timer_set_source(pwm_dev[i].timer,
OMAP_TIMER_SRC_SYS_CLK))
goto timer_init_fail;
clk_enable(fclk);

Next, the module removing reinserting problem seems to be the same
issue. The clk is never being disabled (usecount decremented) when the
module is removed so the next time it can't set the source and the
disable/enable I have in place does not work since the usecount is now
2 instead of 1 and since clk_disable only decrements by 1 usecount is
not 0. I just added a clk_disable to the pwm_timer_cleanup() function:

static void pwm_timer_cleanup(void)
{
int i;
struct clk *fclk;

| for (i = 0; i < num_timers; i++) {
pwm_off(&pwm_dev[i]);
|

//ADDED CODE
fclk = omap_dm_timer_get_fclk(pwm_dev[i].timer);
clk_disable(fclk);
//END ADDED CODE

| if (pwm_dev[i].timer) {
omap_dm_timer_free(pwm_dev[i].timer);
pwm_dev[i].timer = NULL;
if (irq_mode)
free_irq(pwm_dev[i].irq, &pwm_dev[i]);
}

         pwm_restore_mux(&pwm_dev[i]);

 }

|
|

}


Reply to this email directly or view it on GitHub
#3 (comment).

@svolpe
svolpe commented Jul 18, 2013

CONFIG_OMAP_RESET_CLOCKS is set to no on mine. I will try to set it to yes as it does make sense that it could be the difference between our systems.

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