Message ID | 20210531044608.1006024-1-roman.beranek@prusa3d.com (mailing list archive) |
---|---|
Headers | show |
Series | pwm: sun4i: only wait 2 cycles prior to disabling | expand |
On 2021-05-31 06:46, Roman Beranek wrote: > As Emil Lenngren has previously shown [1], actually only 1-2 cycles of > the prescaler-divided clock are necessary to pass before the PWM turns > off, not a full period. > > To avoid having the PWM re-enabled from another thread while asleep, > ctrl_lock spinlock was converted to a mutex so that it can be released > only after the clock gate has finally been turned on. > > [1] https://linux-sunxi.org/PWM_Controller_Register_Guide > > Roman Beranek (6): > pwm: sun4i: enable clk prior to getting its rate > pwm: sun4i: disable EN bit prior to the delay > pwm: sun4i: replace spinlock with a mutex > pwm: sun4i: simplify calculation of the delay time > pwm: sun4i: shorten the delay to 2 cycles > pwm: sun4i: don't delay if the PWM is already off > > drivers/pwm/pwm-sun4i.c | 56 +++++++++++++++++++---------------------- > 1 file changed, 26 insertions(+), 30 deletions(-) Hi Roman, Thanks for your attempt to fix this. Unfortunately on my A10 device (Topwise A721), the controller still gets stuck in an unrecoverable state after disabling and re-enabling the PWM when it was already on (set in U-Boot), or when enabling it when it was off. In this state, any changes to the period register (using devmem) don't seem to have any effect. It seems to be stuck in the state it was before disabling. The only thing which still works is enabling and disabling. I can't reproduce this behavior manually so I'm not sure what is causing this. Regarding the amount of cycles of sleep; Using a prescaler of 72000 the PWM clock is 3 ms. Although timing tests using devmem seem unreliable (too much overhead?), in U-Boot I need to 'sleep' for at least 7 ms between the commands to make sure the output doesn't sometimes get stuck in the enabled state. So in my case it seems to be at least 3 cycles. I am not sure how reliable this method is. However even if I can get it stuck in the enabled state using a shorter time, it doesn't cause the behavior I mentioned before. I was always able to recover it manually. Increasing the number of cycles to sleep therefore also doesn't solve my problem. Until we can solve that I cannot confirm nor deny if 2 cycles is enough. Regards, Pascal
Den mån 31 maj 2021 kl 21:07 skrev Pascal Roeleven <dev@pascalroeleven.nl>: > > On 2021-05-31 06:46, Roman Beranek wrote: > > As Emil Lenngren has previously shown [1], actually only 1-2 cycles of > > the prescaler-divided clock are necessary to pass before the PWM turns > > off, not a full period. > > > > To avoid having the PWM re-enabled from another thread while asleep, > > ctrl_lock spinlock was converted to a mutex so that it can be released > > only after the clock gate has finally been turned on. > > > > [1] https://linux-sunxi.org/PWM_Controller_Register_Guide > > > > Roman Beranek (6): > > pwm: sun4i: enable clk prior to getting its rate > > pwm: sun4i: disable EN bit prior to the delay > > pwm: sun4i: replace spinlock with a mutex > > pwm: sun4i: simplify calculation of the delay time > > pwm: sun4i: shorten the delay to 2 cycles > > pwm: sun4i: don't delay if the PWM is already off > > > > drivers/pwm/pwm-sun4i.c | 56 +++++++++++++++++++---------------------- > > 1 file changed, 26 insertions(+), 30 deletions(-) > > Hi Roman, > > Thanks for your attempt to fix this. > > Unfortunately on my A10 device (Topwise A721), the controller still gets > stuck in an unrecoverable state after disabling and re-enabling the PWM > when it was already on (set in U-Boot), or when enabling it when it was > off. In this state, any changes to the period register (using devmem) > don't seem to have any effect. It seems to be stuck in the state it was > before disabling. The only thing which still works is enabling and > disabling. > > I can't reproduce this behavior manually so I'm not sure what is causing > this. > > Regarding the amount of cycles of sleep; Using a prescaler of 72000 the > PWM clock is 3 ms. Although timing tests using devmem seem unreliable > (too much overhead?), in U-Boot I need to 'sleep' for at least 7 ms > between the commands to make sure the output doesn't sometimes get stuck > in the enabled state. So in my case it seems to be at least 3 cycles. I > am not sure how reliable this method is. However even if I can get it > stuck in the enabled state using a shorter time, it doesn't cause the > behavior I mentioned before. I was always able to recover it manually. > Increasing the number of cycles to sleep therefore also doesn't solve my > problem. Until we can solve that I cannot confirm nor deny if 2 cycles > is enough. > > Regards, > Pascal You could look at the devmem source code, and in C write a script that writes to pwm register to disable the pwm, insert a usleep, then disable the gating. This can be done for various sleep values, then retrying with same sleep value multiple times. Assuming the overhead is low (you can check the overhead by checking the current timestamp at the beginning and at the end of the program, take the diff and then subtract the sleep time), you will get one range where it never works, one range where it works sometimes, and one range where it always works. The uncertain range's condition for succeeding will depend on when in the cycle you run the code. Assuming we believe 3 cycles are enough on A10 and prescaler is 72000, the thresholds for these ranges are 0-6 ms, 6-9 ms and 9+ ms. About "being stuck", I'm not sure exactly what you mean but it's expected that writes to the period register won't be visible (if you read it after a write) when the clock gating is disabled. Three full cycles (with the gating is on) must take place before the change is visible (i.e. need to wait four cycles to be sure). At least on >=A13. I documented that here: https://linux-sunxi.org/PWM_Controller_Register_Guide. /Emil
On 2021-05-31 22:01, Emil Lenngren wrote: > You could look at the devmem source code, and in C write a script that > writes to pwm register to disable the pwm, insert a usleep, then > disable the gating. This can be done for various sleep values, then > retrying with same sleep value multiple times. Assuming the overhead > is low (you can check the overhead by checking the current timestamp > at the beginning and at the end of the program, take the diff and then > subtract the sleep time), you will get one range where it never works, > one range where it works sometimes, and one range where it always > works. The uncertain range's condition for succeeding will depend on > when in the cycle you run the code. > Assuming we believe 3 cycles are enough on A10 and prescaler is 72000, > the thresholds for these ranges are 0-6 ms, 6-9 ms and 9+ ms. Thank you I will give this a shot if there is still an uncertainty about the cycles in the end. I performed my tests with a Busybox rootfs, so I assumed the overhead was low as well. > About "being stuck", I'm not sure exactly what you mean but it's > expected that writes to the period register won't be visible (if you > read it after a write) when the clock gating is disabled. Three full > cycles (with the gating is on) must take place before the change is > visible (i.e. need to wait four cycles to be sure). At least on >=A13. > I documented that here: > https://linux-sunxi.org/PWM_Controller_Register_Guide. By being stuck, I mean being in an state from which it can't recover. The controller will keep outputting seemingly the same signal regardless what you write to the period register. You can read the values back, but they aren't effecting the output anymore. No matter in what order or with what delay I try to re-enable and disable the gate or enable bit, it'll keep outputting the same signal until you reset the device.
On 2021-05-31 21:07, Pascal Roeleven wrote: > On 2021-05-31 06:46, Roman Beranek wrote: >> As Emil Lenngren has previously shown [1], actually only 1-2 cycles of >> the prescaler-divided clock are necessary to pass before the PWM turns >> off, not a full period. >> >> To avoid having the PWM re-enabled from another thread while asleep, >> ctrl_lock spinlock was converted to a mutex so that it can be released >> only after the clock gate has finally been turned on. >> >> [1] https://linux-sunxi.org/PWM_Controller_Register_Guide >> >> Roman Beranek (6): >> pwm: sun4i: enable clk prior to getting its rate >> pwm: sun4i: disable EN bit prior to the delay >> pwm: sun4i: replace spinlock with a mutex >> pwm: sun4i: simplify calculation of the delay time >> pwm: sun4i: shorten the delay to 2 cycles >> pwm: sun4i: don't delay if the PWM is already off >> >> drivers/pwm/pwm-sun4i.c | 56 +++++++++++++++++++---------------------- >> 1 file changed, 26 insertions(+), 30 deletions(-) > > Hi Roman, > > Thanks for your attempt to fix this. > > Unfortunately on my A10 device (Topwise A721), the controller still gets > stuck in an unrecoverable state after disabling and re-enabling the PWM > when it was already on (set in U-Boot), or when enabling it when it was > off. In this state, any changes to the period register (using devmem) > don't seem to have any effect. It seems to be stuck in the state it was > before disabling. The only thing which still works is enabling and > disabling. > > I can't reproduce this behavior manually so I'm not sure what is causing > this. > > Regarding the amount of cycles of sleep; Using a prescaler of 72000 the > PWM clock is 3 ms. Although timing tests using devmem seem unreliable > (too much overhead?), in U-Boot I need to 'sleep' for at least 7 ms > between the commands to make sure the output doesn't sometimes get stuck > in the enabled state. So in my case it seems to be at least 3 cycles. I > am not sure how reliable this method is. However even if I can get it > stuck in the enabled state using a shorter time, it doesn't cause the > behavior I mentioned before. I was always able to recover it manually. > Increasing the number of cycles to sleep therefore also doesn't solve my > problem. Until we can solve that I cannot confirm nor deny if 2 cycles > is enough. > > Regards, > Pascal Turns out, what I'm referring to here is actually a different issue not related to this patch series. A different series might be sent later to address that. So no objections from my side for this one. Regards, Pascal