Hi Notaz,
Am 15.02.2016 um 23:40 schrieb Grazvydas Ignotas grazvydas.ignotas@openpandora.org:
On 02/15/2016 11:38 PM, H. Nikolaus Schaller wrote:
<snip> Here a log if someone can help to decipher.
[ 5.586922] driver_register 'pwm-backlight' [ 5.591702] backlight supply power not found, using dummy regulator [ 5.599205] ------------[ cut here ]------------ [ 5.604038] WARNING: CPU: 0 PID: 962 at drivers/bus/omap_l3_noc.c:147 l3_handle_target+0x1b0/0x204() [ 5.613602] 44000000.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access
This looks like OMAP5 is being unhappy about dmtimer clock disable, supposedly some L3 interconnect access still in progress?
Maybe something like this would help (untested in any way):
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 7a327bd..af38614 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -670,6 +670,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, l |= OMAP_TIMER_CTRL_PT; l |= trigger << 10; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
__omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, 1);
brilliant!
That made this error go away and reappear somewhere else. After applying the same fix to several other locations where timer registers are written I could make them all go away.
But IMHO there is a deeper issue. The third parameter of __omap_dm_timer_read() is called "posted" and setting it to 1 makes the driver wait for some activity to finish.
There is also a comment in omap_dm_timer_read_reg() which says:
"The posted mode bit is encoded in reg."
But the code does not "decode" it depending on the register number. Rather there is a timer->posted flag which is set or reset globally depending on how the driver is initialized or if __omap_dm_timer_enable_posted() is called.
This appears to be hooked up from the wrong end. Either the SoC (L3 interconnect) needs this posting mechanism or it does not. How can the code using the driver know better than the driver itself.
And maybe on OMAP5 we need it. While on OMAP3 we don't (because the A8 is slower but L3 might have similar speed). So it does not depend on what the user of the dmtimer wants to have.
BTW: there was also some "cleanup" proposed a while ago, but did not find it into mainline:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/117682....
which also shows the "wrong" approach. Why should it be possible to "configure" the whole timer to posted mode. IMHO it is sort of transaction processing, i.e. grouping register writes and then committing them. So it depends on the sequence of write commands.
Well, for the moment we have a fix to silence these kernel messages which is sufficient for my hardware validation, i.e. we can leave this open for future improvements as soon as we have stable OMAP5 dual core operation.
/* Save the context */ timer->context.tclr = l;
... or maybe adding some udelay() there instead. It that doesn't help, perhaps dmtimer clock can't be disabled while pwm is in use? I'm talking about omap_dm_timer_disable() in omap_dm_timer_set_pwm().
Grazvydas
BR and thanks for the help, Nikolaus
PS: Now I have a login: after ca. 20 seconds and X11+LCD after ~30 seconds.
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 7a327bd..bdc549d 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -476,6 +476,7 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) if (!(l & OMAP_TIMER_CTRL_ST)) { l |= OMAP_TIMER_CTRL_ST; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, 1); }
/* Save the context */ @@ -589,6 +590,8 @@ int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); + __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, 1); + /* Save the context */ timer->context.tclr = l; timer->context.tldr = load; @@ -605,7 +608,7 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
if (unlikely(!timer)) return -EINVAL; - +printk("dmtimer posted=%d\n", timer->posted); omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); @@ -643,6 +646,7 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, l &= ~OMAP_TIMER_CTRL_CE; omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, 1);
/* Save the context */ timer->context.tclr = l; @@ -670,6 +674,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, l |= OMAP_TIMER_CTRL_PT; l |= trigger << 10; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, 1);
/* Save the context */ timer->context.tclr = l; @@ -794,6 +799,7 @@ int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) }
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); + __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, 1);
/* Save the context */ timer->context.tcrr = value;