Message ID | 20210329125707.182732-4-clemens.gruber@pqgruber.com |
---|---|
State | Superseded |
Headers | show |
Series | [v6,1/7] pwm: pca9685: Switch to atomic API | expand |
On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > The PCA9685 supports staggered LED output ON times to minimize current > surges and reduce EMI. > When this new option is enabled, the ON times of each channel are > delayed by channel number x counter range / 16, which avoids asserting > all enabled outputs at the same counter value while still maintaining > the configured duty cycle of each output. > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> Is there a reason to not want this staggered output? If it never hurts I suggest to always stagger and drop the dt property. Best regards Uwe
On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > The PCA9685 supports staggered LED output ON times to minimize current > > surges and reduce EMI. > > When this new option is enabled, the ON times of each channel are > > delayed by channel number x counter range / 16, which avoids asserting > > all enabled outputs at the same counter value while still maintaining > > the configured duty cycle of each output. > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > Is there a reason to not want this staggered output? If it never hurts I > suggest to always stagger and drop the dt property. There might be applications where you want multiple outputs to assert at the same time / to be synchronized. With staggered outputs mode always enabled, this would no longer be possible as they are spread out according to their channel number. Not sure how often that usecase is required, but just enforcing the staggered mode by default sounds risky to me. Thanks, Clemens
On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > The PCA9685 supports staggered LED output ON times to minimize current > > > surges and reduce EMI. > > > When this new option is enabled, the ON times of each channel are > > > delayed by channel number x counter range / 16, which avoids asserting > > > all enabled outputs at the same counter value while still maintaining > > > the configured duty cycle of each output. > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > Is there a reason to not want this staggered output? If it never hurts I > > suggest to always stagger and drop the dt property. > > There might be applications where you want multiple outputs to assert at > the same time / to be synchronized. > With staggered outputs mode always enabled, this would no longer be > possible as they are spread out according to their channel number. > > Not sure how often that usecase is required, but just enforcing the > staggered mode by default sounds risky to me. There is no such guarantee in the PWM framework, so I don't think we need to fear breaking setups. Thierry? One reason we might not want staggering is if we have a consumer who cares about config transitions. (This however is moot it the hardware doesn't provide sane transitions even without staggering.) Did I already ask about races in this driver? I assume there is a free running counter and the ON and OFF registers just define where in the period the transitions happen, right? Given that changing ON and OFF needs two register writes probably all kind of strange things can happen, right? (Example thought: for simplicity's sake I assume ON is always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we might see a period with 0xacc. Depending on how the hardware works we might even see 4 edges in a single period then.) Best regards Uwe
On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > surges and reduce EMI. > > > > When this new option is enabled, the ON times of each channel are > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > all enabled outputs at the same counter value while still maintaining > > > > the configured duty cycle of each output. > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > suggest to always stagger and drop the dt property. > > > > There might be applications where you want multiple outputs to assert at > > the same time / to be synchronized. > > With staggered outputs mode always enabled, this would no longer be > > possible as they are spread out according to their channel number. > > > > Not sure how often that usecase is required, but just enforcing the > > staggered mode by default sounds risky to me. > > There is no such guarantee in the PWM framework, so I don't think we > need to fear breaking setups. Thierry? Still, someone might rely on it? But let's wait for Thierry's opinion. > > One reason we might not want staggering is if we have a consumer who > cares about config transitions. (This however is moot it the hardware > doesn't provide sane transitions even without staggering.) > > Did I already ask about races in this driver? I assume there is a > free running counter and the ON and OFF registers just define where in > the period the transitions happen, right? Given that changing ON and OFF > needs two register writes probably all kind of strange things can > happen, right? (Example thought: for simplicity's sake I assume ON is > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > might see a period with 0xacc. Depending on how the hardware works we > might even see 4 edges in a single period then.) Yes, there is a free running counter from 0 to 4095. And it is probably true, that there can be short intermediate states with our two register writes. There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), which is 0 by default (Outputs change on STOP command) but could be set to 1 (Outputs change on ACK): "Update on ACK requires all 4 PWM channel registers to be loaded before outputs will change on the last ACK." The chip datasheet also states: "Because the loading of the LEDn_ON and LEDn_OFF registers is via the I2C-bus, and asynchronous to the internal oscillator, we want to ensure that we do not see any visual artifacts of changing the ON and OFF values. This is achieved by updating the changes at the end of the LOW cycle." We could look into this in a future patch series, however I would like to keep the register updating as-is for this series (otherwise I would have to do all the tests with the oscilloscope again and the transitions were like this since the driver was first implemented). Thanks, Clemens
On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > surges and reduce EMI. > > > > > When this new option is enabled, the ON times of each channel are > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > all enabled outputs at the same counter value while still maintaining > > > > > the configured duty cycle of each output. > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > suggest to always stagger and drop the dt property. > > > > > > There might be applications where you want multiple outputs to assert at > > > the same time / to be synchronized. > > > With staggered outputs mode always enabled, this would no longer be > > > possible as they are spread out according to their channel number. > > > > > > Not sure how often that usecase is required, but just enforcing the > > > staggered mode by default sounds risky to me. > > > > There is no such guarantee in the PWM framework, so I don't think we > > need to fear breaking setups. Thierry? > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > > > > One reason we might not want staggering is if we have a consumer who > > cares about config transitions. (This however is moot it the hardware > > doesn't provide sane transitions even without staggering.) > > > > Did I already ask about races in this driver? I assume there is a > > free running counter and the ON and OFF registers just define where in > > the period the transitions happen, right? Given that changing ON and OFF > > needs two register writes probably all kind of strange things can > > happen, right? (Example thought: for simplicity's sake I assume ON is > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > might see a period with 0xacc. Depending on how the hardware works we > > might even see 4 edges in a single period then.) > > Yes, there is a free running counter from 0 to 4095. > And it is probably true, that there can be short intermediate states > with our two register writes. > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > which is 0 by default (Outputs change on STOP command) but could be set > to 1 (Outputs change on ACK): > "Update on ACK requires all 4 PWM channel registers to be loaded before > outputs will change on the last ACK." This would require the auto-increment feature to be enabled, then multiple registers could be written before the STOP condition: LEDn_ON_L, LEDn_ON_H, LEDn_OFF_L & LEDn_OFF_H (With OCH=0 in MODE2) But I think this should be done in a separate improvement patch/series to reduce glitches. > The chip datasheet also states: > "Because the loading of the LEDn_ON and LEDn_OFF registers is via the > I2C-bus, and asynchronous to the internal oscillator, we want to ensure > that we do not see any visual artifacts of changing the ON and OFF > values. This is achieved by updating the changes at the end of the LOW > cycle." > > We could look into this in a future patch series, however I would like > to keep the register updating as-is for this series (otherwise I would > have to do all the tests with the oscilloscope again and the transitions > were like this since the driver was first implemented). > > Thanks, > Clemens
On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > surges and reduce EMI. > > > > > When this new option is enabled, the ON times of each channel are > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > all enabled outputs at the same counter value while still maintaining > > > > > the configured duty cycle of each output. > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > suggest to always stagger and drop the dt property. > > > > > > There might be applications where you want multiple outputs to assert at > > > the same time / to be synchronized. > > > With staggered outputs mode always enabled, this would no longer be > > > possible as they are spread out according to their channel number. > > > > > > Not sure how often that usecase is required, but just enforcing the > > > staggered mode by default sounds risky to me. > > > > There is no such guarantee in the PWM framework, so I don't think we > > need to fear breaking setups. Thierry? > > Still, someone might rely on it? But let's wait for Thierry's opinion. There's currently no way to synchronize two PWM channels in the PWM framework. And given that each PWM channel is handled separately the programming for two channels will never happen atomically or even concurrently, so I don't see how you could run two PWMs completely synchronized to one another. That said, it might be possible to implement something like this by coupling two or more PWMs. However, I think we will only ever be able to do this on a per-chip basis, because that's the only way we could guarantee that multiple PWMs can be programmed at the same time, or that they get enabled with the same write. Of course this all requires that the chip even supports that. Even if you enable two PWM channels within the same driver but with two consecutive register writes they will not be guaranteed to run synchronously. There'd have to be some special chip support to allow this to work. However, I'm a bit hesitant about this staggering output mode. From what I understand what's going to happen for these is basically that overall each PWM will be running at the requested duty cycle, but the on/off times will be evenly spread out over the whole period. In other words, the output *power* of the PWM signal will be the same as if the signal was a single on/off cycle. That's not technically a PWM signal as the PWM framework defines it. See the kerneldoc for enum pwm_polarity for what signals are expected to look like. So I agree that this is not something that should be enabled by default because if you've got a consumer that expects exactly one rising edge and one falling edge per period, they will get confused if you toggle multiple times during one period. If that's the case,you probably want to configure this on a per-PWM basis rather than for the entire chip because otherwise you could end up in a scenario where one PWM does *not* work with staggered output and the others do. I guess you could always make that decision up front, but do you always know what people may end up using these PWMs for? What if you have a board that breaks out one PWM on some general purpose pin header and people end up using it via sysfs. They would need have to recompile the DTB for the device if they wanted to enable or disable this staggered mode. Or did I misunderstand and it's only the start time of the rising edge that's shifted, but the signal will remain high for a full duty cycle after that and then go down and remain low for period - duty - offset? That's slightly better than the above in that it likely won't trip up any consumers. But it might still be worth to make this configurable per PWM (perhaps by specifying a third specifier cell, in addition to the period and flags, that defines the offset/phase of the signal). In both cases, doing this on a per-PWM basis will allow the consumer to specify that they're okay with staggered mode and you won't actually force it onto anyone. This effectively makes this opt-in and there will be no change for existing consumers. > > One reason we might not want staggering is if we have a consumer who > > cares about config transitions. (This however is moot it the hardware > > doesn't provide sane transitions even without staggering.) > > > > Did I already ask about races in this driver? I assume there is a > > free running counter and the ON and OFF registers just define where in > > the period the transitions happen, right? Given that changing ON and OFF > > needs two register writes probably all kind of strange things can > > happen, right? (Example thought: for simplicity's sake I assume ON is > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > might see a period with 0xacc. Depending on how the hardware works we > > might even see 4 edges in a single period then.) > > Yes, there is a free running counter from 0 to 4095. > And it is probably true, that there can be short intermediate states > with our two register writes. > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > which is 0 by default (Outputs change on STOP command) but could be set > to 1 (Outputs change on ACK): > "Update on ACK requires all 4 PWM channel registers to be loaded before > outputs will change on the last ACK." This sounds like it would allow atomic updates of the PWM settings. That's probably something that you want to implement to avoid any glitches. > The chip datasheet also states: > "Because the loading of the LEDn_ON and LEDn_OFF registers is via the > I2C-bus, and asynchronous to the internal oscillator, we want to ensure > that we do not see any visual artifacts of changing the ON and OFF > values. This is achieved by updating the changes at the end of the LOW > cycle." > > We could look into this in a future patch series, however I would like > to keep the register updating as-is for this series (otherwise I would > have to do all the tests with the oscilloscope again and the transitions > were like this since the driver was first implemented). Yeah, it sounds fine to implement this at a later point in time. No need to conflate it with the current series. Thierry
Hi Thierry, On Wed, Mar 31, 2021 at 06:21:32PM +0200, Thierry Reding wrote: > On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > > surges and reduce EMI. > > > > > > When this new option is enabled, the ON times of each channel are > > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > > all enabled outputs at the same counter value while still maintaining > > > > > > the configured duty cycle of each output. > > > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > > suggest to always stagger and drop the dt property. > > > > > > > > There might be applications where you want multiple outputs to assert at > > > > the same time / to be synchronized. > > > > With staggered outputs mode always enabled, this would no longer be > > > > possible as they are spread out according to their channel number. > > > > > > > > Not sure how often that usecase is required, but just enforcing the > > > > staggered mode by default sounds risky to me. > > > > > > There is no such guarantee in the PWM framework, so I don't think we > > > need to fear breaking setups. Thierry? > > > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > There's currently no way to synchronize two PWM channels in the PWM > framework. And given that each PWM channel is handled separately the > programming for two channels will never happen atomically or even > concurrently, so I don't see how you could run two PWMs completely > synchronized to one another. As the PCA9685 has only one prescaler and one counter per chip, by default, all PWMs enabled will go high at the same time. If they also have the same duty cycle configured, they also go low at the same time. > Or did I misunderstand and it's only the start time of the rising edge > that's shifted, but the signal will remain high for a full duty cycle > after that and then go down and remain low for period - duty - offset? Yes, that's how it works. > > That's slightly better than the above in that it likely won't trip up > any consumers. But it might still be worth to make this configurable per > PWM (perhaps by specifying a third specifier cell, in addition to the > period and flags, that defines the offset/phase of the signal). > > In both cases, doing this on a per-PWM basis will allow the consumer to > specify that they're okay with staggered mode and you won't actually > force it onto anyone. This effectively makes this opt-in and there will > be no change for existing consumers. I agree that it should be opt-in, but I am not sure about doing it per-pwm: The reason why you'd want staggered mode is to reduce EMI or current spikes and it is most effective if it is enabled for all PWMs. If it is specified in the DT anyway and you have a consumer that does not support staggered mode (probably rare but can happen), then I'd suggest just disabling it globally by not specifying nxp,staggered-mode; Also it would make the configuration more complicated: You have to do the "staggering" yourself and assign offsets per channel. It's certainly easier to just enable or disable it. What do you think? > > > One reason we might not want staggering is if we have a consumer who > > > cares about config transitions. (This however is moot it the hardware > > > doesn't provide sane transitions even without staggering.) > > > > > > Did I already ask about races in this driver? I assume there is a > > > free running counter and the ON and OFF registers just define where in > > > the period the transitions happen, right? Given that changing ON and OFF > > > needs two register writes probably all kind of strange things can > > > happen, right? (Example thought: for simplicity's sake I assume ON is > > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > > might see a period with 0xacc. Depending on how the hardware works we > > > might even see 4 edges in a single period then.) > > > > Yes, there is a free running counter from 0 to 4095. > > And it is probably true, that there can be short intermediate states > > with our two register writes. > > > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > > which is 0 by default (Outputs change on STOP command) but could be set > > to 1 (Outputs change on ACK): > > "Update on ACK requires all 4 PWM channel registers to be loaded before > > outputs will change on the last ACK." > > This sounds like it would allow atomic updates of the PWM settings. > That's probably something that you want to implement to avoid any > glitches. > > > The chip datasheet also states: > > "Because the loading of the LEDn_ON and LEDn_OFF registers is via the > > I2C-bus, and asynchronous to the internal oscillator, we want to ensure > > that we do not see any visual artifacts of changing the ON and OFF > > values. This is achieved by updating the changes at the end of the LOW > > cycle." > > > > We could look into this in a future patch series, however I would like > > to keep the register updating as-is for this series (otherwise I would > > have to do all the tests with the oscilloscope again and the transitions > > were like this since the driver was first implemented). > > Yeah, it sounds fine to implement this at a later point in time. No need > to conflate it with the current series. Sounds good. Thanks, Clemens
On Thu, Apr 01, 2021 at 09:50:44AM +0200, Clemens Gruber wrote: > Hi Thierry, > > On Wed, Mar 31, 2021 at 06:21:32PM +0200, Thierry Reding wrote: > > On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > > > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > > > surges and reduce EMI. > > > > > > > When this new option is enabled, the ON times of each channel are > > > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > > > all enabled outputs at the same counter value while still maintaining > > > > > > > the configured duty cycle of each output. > > > > > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > > > suggest to always stagger and drop the dt property. > > > > > > > > > > There might be applications where you want multiple outputs to assert at > > > > > the same time / to be synchronized. > > > > > With staggered outputs mode always enabled, this would no longer be > > > > > possible as they are spread out according to their channel number. > > > > > > > > > > Not sure how often that usecase is required, but just enforcing the > > > > > staggered mode by default sounds risky to me. > > > > > > > > There is no such guarantee in the PWM framework, so I don't think we > > > > need to fear breaking setups. Thierry? > > > > > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > > > There's currently no way to synchronize two PWM channels in the PWM > > framework. And given that each PWM channel is handled separately the > > programming for two channels will never happen atomically or even > > concurrently, so I don't see how you could run two PWMs completely > > synchronized to one another. > > As the PCA9685 has only one prescaler and one counter per chip, by > default, all PWMs enabled will go high at the same time. If they also > have the same duty cycle configured, they also go low at the same time. What happens if you enable one of them, it then goes high and then you enable the next one? Is the second one going to get enabled on the next period? Or will it start in the middle of the period? To truly enable them atomically, you'd have to ensure they all get enabled in basically the same write, right? Because otherwise you can still end up with just a subset enabled and the rest getting enabled only after the first period. > > Or did I misunderstand and it's only the start time of the rising edge > > that's shifted, but the signal will remain high for a full duty cycle > > after that and then go down and remain low for period - duty - offset? > > Yes, that's how it works. That's less problematic because the signal will remain a standard PWM, it's just shifted by some amount. Technically pwm_apply_state() must only return when the signal has been enabled, so very strictly speaking you'd have to wait for a given amount of time to ensure that's correct. But again, I doubt that any use-case would require you to be that deterministic. > > That's slightly better than the above in that it likely won't trip up > > any consumers. But it might still be worth to make this configurable per > > PWM (perhaps by specifying a third specifier cell, in addition to the > > period and flags, that defines the offset/phase of the signal). > > > > In both cases, doing this on a per-PWM basis will allow the consumer to > > specify that they're okay with staggered mode and you won't actually > > force it onto anyone. This effectively makes this opt-in and there will > > be no change for existing consumers. > > I agree that it should be opt-in, but I am not sure about doing it > per-pwm: > The reason why you'd want staggered mode is to reduce EMI or current > spikes and it is most effective if it is enabled for all PWMs. > > If it is specified in the DT anyway and you have a consumer that does > not support staggered mode (probably rare but can happen), then I'd > suggest just disabling it globally by not specifying nxp,staggered-mode; > > Also it would make the configuration more complicated: You have to do > the "staggering" yourself and assign offsets per channel. > It's certainly easier to just enable or disable it. > > What do you think? Yeah, if you use an offset in the PWM specifier, users would have to manually specify the offset. An interesting "feature" of that would be that they could configure a subset of PWM channels to run synchronized (module the atomicity problems discussed above). Not sure if that's something anyone would ever want to do. Another option would be to add some new flag that specifies that a given PWM channel may use this mode. In that case users wouldn't have to care about specifying the exact offset and instead just use the flag and rely on the driver to pick some offset. Within the driver you could then just keep the same computation that offsets by channel index, or you could have any other mechanism that you want. Thierry
On Thu, Apr 01, 2021 at 03:47:26PM +0200, Thierry Reding wrote: > On Thu, Apr 01, 2021 at 09:50:44AM +0200, Clemens Gruber wrote: > > Hi Thierry, > > > > On Wed, Mar 31, 2021 at 06:21:32PM +0200, Thierry Reding wrote: > > > On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > > > > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > > > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > > > > surges and reduce EMI. > > > > > > > > When this new option is enabled, the ON times of each channel are > > > > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > > > > all enabled outputs at the same counter value while still maintaining > > > > > > > > the configured duty cycle of each output. > > > > > > > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > > > > suggest to always stagger and drop the dt property. > > > > > > > > > > > > There might be applications where you want multiple outputs to assert at > > > > > > the same time / to be synchronized. > > > > > > With staggered outputs mode always enabled, this would no longer be > > > > > > possible as they are spread out according to their channel number. > > > > > > > > > > > > Not sure how often that usecase is required, but just enforcing the > > > > > > staggered mode by default sounds risky to me. > > > > > > > > > > There is no such guarantee in the PWM framework, so I don't think we > > > > > need to fear breaking setups. Thierry? > > > > > > > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > > > > > There's currently no way to synchronize two PWM channels in the PWM > > > framework. And given that each PWM channel is handled separately the > > > programming for two channels will never happen atomically or even > > > concurrently, so I don't see how you could run two PWMs completely > > > synchronized to one another. > > > > As the PCA9685 has only one prescaler and one counter per chip, by > > default, all PWMs enabled will go high at the same time. If they also > > have the same duty cycle configured, they also go low at the same time. > > What happens if you enable one of them, it then goes high and then you > enable the next one? Is the second one going to get enabled on the next > period? Or will it start in the middle of the period? The channel configuration is updated at the end of the low cycle of the channel in question and if the counter is already past the ON time, it will start with the next period. So the second one should never start while the first one is high (unless staggering mode is enabled). > To truly enable them atomically, you'd have to ensure they all get > enabled in basically the same write, right? Because otherwise you can > still end up with just a subset enabled and the rest getting enabled > only after the first period. Yes. This could probably be achieved with auto-increment for consecutive channels or with the special ALL channel for all channels. In our usecases this is not required. I'd still like to send a follow up patch in the future that at least implements the register writes per channel with auto increment to not have intermediate states (due to high and low byte being written separately) > > > Or did I misunderstand and it's only the start time of the rising edge > > > that's shifted, but the signal will remain high for a full duty cycle > > > after that and then go down and remain low for period - duty - offset? > > > > Yes, that's how it works. > > That's less problematic because the signal will remain a standard PWM, > it's just shifted by some amount. Technically pwm_apply_state() must > only return when the signal has been enabled, so very strictly speaking > you'd have to wait for a given amount of time to ensure that's correct. > But again, I doubt that any use-case would require you to be that > deterministic. Yes, probably not and if we make it opt-in, it shouldn't be a problem. > > > > That's slightly better than the above in that it likely won't trip up > > > any consumers. But it might still be worth to make this configurable per > > > PWM (perhaps by specifying a third specifier cell, in addition to the > > > period and flags, that defines the offset/phase of the signal). > > > > > > In both cases, doing this on a per-PWM basis will allow the consumer to > > > specify that they're okay with staggered mode and you won't actually > > > force it onto anyone. This effectively makes this opt-in and there will > > > be no change for existing consumers. > > > > I agree that it should be opt-in, but I am not sure about doing it > > per-pwm: > > The reason why you'd want staggered mode is to reduce EMI or current > > spikes and it is most effective if it is enabled for all PWMs. > > > > If it is specified in the DT anyway and you have a consumer that does > > not support staggered mode (probably rare but can happen), then I'd > > suggest just disabling it globally by not specifying nxp,staggered-mode; > > > > Also it would make the configuration more complicated: You have to do > > the "staggering" yourself and assign offsets per channel. > > It's certainly easier to just enable or disable it. > > > > What do you think? > > Yeah, if you use an offset in the PWM specifier, users would have to > manually specify the offset. An interesting "feature" of that would be > that they could configure a subset of PWM channels to run synchronized > (module the atomicity problems discussed above). Not sure if that's > something anyone would ever want to do. Yes and for the common case where you don't care it would be more work for the user. > > Another option would be to add some new flag that specifies that a given > PWM channel may use this mode. In that case users wouldn't have to care > about specifying the exact offset and instead just use the flag and rely > on the driver to pick some offset. Within the driver you could then just > keep the same computation that offsets by channel index, or you could > have any other mechanism that you want. OK, so maybe a PWM_STAGGERING_ALLOWED flag in dt-bindings/pwm/pwm.h, pass it through via a new bool staggering_allowed in struct pwm_args? Thanks, Clemens
Hello Clemens, On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > surges and reduce EMI. > > > > > When this new option is enabled, the ON times of each channel are > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > all enabled outputs at the same counter value while still maintaining > > > > > the configured duty cycle of each output. > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > suggest to always stagger and drop the dt property. > > > > > > There might be applications where you want multiple outputs to assert at > > > the same time / to be synchronized. > > > With staggered outputs mode always enabled, this would no longer be > > > possible as they are spread out according to their channel number. > > > > > > Not sure how often that usecase is required, but just enforcing the > > > staggered mode by default sounds risky to me. > > > > There is no such guarantee in the PWM framework, so I don't think we > > need to fear breaking setups. Thierry? > > Still, someone might rely on it? But let's wait for Thierry's opinion. Someone might rely on the pca9685 driver being as racy as a driver with legacy bindings usually is. Should this be the reason to drop this whole series? > > One reason we might not want staggering is if we have a consumer who > > cares about config transitions. (This however is moot it the hardware > > doesn't provide sane transitions even without staggering.) > > > > Did I already ask about races in this driver? I assume there is a > > free running counter and the ON and OFF registers just define where in > > the period the transitions happen, right? Given that changing ON and OFF > > needs two register writes probably all kind of strange things can > > happen, right? (Example thought: for simplicity's sake I assume ON is > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > might see a period with 0xacc. Depending on how the hardware works we > > might even see 4 edges in a single period then.) > > Yes, there is a free running counter from 0 to 4095. > And it is probably true, that there can be short intermediate states > with our two register writes. > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > which is 0 by default (Outputs change on STOP command) but could be set > to 1 (Outputs change on ACK): > "Update on ACK requires all 4 PWM channel registers to be loaded before > outputs will change on the last ACK." This is about the ACK and STOP in the i2c communication, right? I fail to understand the relevance of this difference. I guess I have to read the manual myself. > The chip datasheet also states: > "Because the loading of the LEDn_ON and LEDn_OFF registers is via the > I2C-bus, and asynchronous to the internal oscillator, we want to ensure > that we do not see any visual artifacts of changing the ON and OFF > values. This is achieved by updating the changes at the end of the LOW > cycle." So we're only out of luck if the first register write happens before and the second after the end of the LOW cycle, aren't we? Best regards Uwe
On Wed, Mar 31, 2021 at 03:55:49PM +0200, Clemens Gruber wrote: > On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > > surges and reduce EMI. > > > > > > When this new option is enabled, the ON times of each channel are > > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > > all enabled outputs at the same counter value while still maintaining > > > > > > the configured duty cycle of each output. > > > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > > suggest to always stagger and drop the dt property. > > > > > > > > There might be applications where you want multiple outputs to assert at > > > > the same time / to be synchronized. > > > > With staggered outputs mode always enabled, this would no longer be > > > > possible as they are spread out according to their channel number. > > > > > > > > Not sure how often that usecase is required, but just enforcing the > > > > staggered mode by default sounds risky to me. > > > > > > There is no such guarantee in the PWM framework, so I don't think we > > > need to fear breaking setups. Thierry? > > > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > > > > > > > One reason we might not want staggering is if we have a consumer who > > > cares about config transitions. (This however is moot it the hardware > > > doesn't provide sane transitions even without staggering.) > > > > > > Did I already ask about races in this driver? I assume there is a > > > free running counter and the ON and OFF registers just define where in > > > the period the transitions happen, right? Given that changing ON and OFF > > > needs two register writes probably all kind of strange things can > > > happen, right? (Example thought: for simplicity's sake I assume ON is > > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > > might see a period with 0xacc. Depending on how the hardware works we > > > might even see 4 edges in a single period then.) > > > > Yes, there is a free running counter from 0 to 4095. > > And it is probably true, that there can be short intermediate states > > with our two register writes. > > > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > > which is 0 by default (Outputs change on STOP command) but could be set > > to 1 (Outputs change on ACK): > > "Update on ACK requires all 4 PWM channel registers to be loaded before > > outputs will change on the last ACK." > > This would require the auto-increment feature to be enabled, then > multiple registers could be written before the STOP condition: > LEDn_ON_L, LEDn_ON_H, LEDn_OFF_L & LEDn_OFF_H > (With OCH=0 in MODE2) Maybe a continued START would work, too?! Best regards Uwe
Hello Uwe, On Thu, Apr 01, 2021 at 10:58:19PM +0200, Uwe Kleine-König wrote: > Hello Clemens, > > On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > > surges and reduce EMI. > > > > > > When this new option is enabled, the ON times of each channel are > > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > > all enabled outputs at the same counter value while still maintaining > > > > > > the configured duty cycle of each output. > > > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > > suggest to always stagger and drop the dt property. > > > > > > > > There might be applications where you want multiple outputs to assert at > > > > the same time / to be synchronized. > > > > With staggered outputs mode always enabled, this would no longer be > > > > possible as they are spread out according to their channel number. > > > > > > > > Not sure how often that usecase is required, but just enforcing the > > > > staggered mode by default sounds risky to me. > > > > > > There is no such guarantee in the PWM framework, so I don't think we > > > need to fear breaking setups. Thierry? > > > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > Someone might rely on the pca9685 driver being as racy as a driver with > legacy bindings usually is. Should this be the reason to drop this whole > series? That's not really a fair comparison. I just don't want the whole staggering mode patch to get reverted someday because it broke someone's setup. If it is opt-in, something like that can't happen. If you say that we don't have to care about usecases that are not officialy guaranteed by the framework, then I'm fine with enabling it by default. But in the meantime, Thierry also argued against enabling it by default. > > > > One reason we might not want staggering is if we have a consumer who > > > cares about config transitions. (This however is moot it the hardware > > > doesn't provide sane transitions even without staggering.) > > > > > > Did I already ask about races in this driver? I assume there is a > > > free running counter and the ON and OFF registers just define where in > > > the period the transitions happen, right? Given that changing ON and OFF > > > needs two register writes probably all kind of strange things can > > > happen, right? (Example thought: for simplicity's sake I assume ON is > > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > > might see a period with 0xacc. Depending on how the hardware works we > > > might even see 4 edges in a single period then.) > > > > Yes, there is a free running counter from 0 to 4095. > > And it is probably true, that there can be short intermediate states > > with our two register writes. > > > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > > which is 0 by default (Outputs change on STOP command) but could be set > > to 1 (Outputs change on ACK): > > "Update on ACK requires all 4 PWM channel registers to be loaded before > > outputs will change on the last ACK." > > This is about the ACK and STOP in the i2c communication, right? I fail > to understand the relevance of this difference. I guess I have to read > the manual myself. Yes. Not sure why they added the other mode myself, as you should be able to send multiple bytes before the STOP with auto-increment as well. But I did not try this out yet as this won't go into this series anyway. I will look into it in more detail and do some experiments as soon as this series is merged. > > > The chip datasheet also states: > > "Because the loading of the LEDn_ON and LEDn_OFF registers is via the > > I2C-bus, and asynchronous to the internal oscillator, we want to ensure > > that we do not see any visual artifacts of changing the ON and OFF > > values. This is achieved by updating the changes at the end of the LOW > > cycle." > > So we're only out of luck if the first register write happens before and > the second after the end of the LOW cycle, aren't we? Yes. And this will be fixed with the auto-increment feature when we can write all registers in one transaction. Thanks, Clemens
On Thu, Apr 01, 2021 at 10:59:36PM +0200, Uwe Kleine-König wrote: > On Wed, Mar 31, 2021 at 03:55:49PM +0200, Clemens Gruber wrote: > > On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > > > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > > > surges and reduce EMI. > > > > > > > When this new option is enabled, the ON times of each channel are > > > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > > > all enabled outputs at the same counter value while still maintaining > > > > > > > the configured duty cycle of each output. > > > > > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > > > suggest to always stagger and drop the dt property. > > > > > > > > > > There might be applications where you want multiple outputs to assert at > > > > > the same time / to be synchronized. > > > > > With staggered outputs mode always enabled, this would no longer be > > > > > possible as they are spread out according to their channel number. > > > > > > > > > > Not sure how often that usecase is required, but just enforcing the > > > > > staggered mode by default sounds risky to me. > > > > > > > > There is no such guarantee in the PWM framework, so I don't think we > > > > need to fear breaking setups. Thierry? > > > > > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > > > > > > > > > > One reason we might not want staggering is if we have a consumer who > > > > cares about config transitions. (This however is moot it the hardware > > > > doesn't provide sane transitions even without staggering.) > > > > > > > > Did I already ask about races in this driver? I assume there is a > > > > free running counter and the ON and OFF registers just define where in > > > > the period the transitions happen, right? Given that changing ON and OFF > > > > needs two register writes probably all kind of strange things can > > > > happen, right? (Example thought: for simplicity's sake I assume ON is > > > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > > > might see a period with 0xacc. Depending on how the hardware works we > > > > might even see 4 edges in a single period then.) > > > > > > Yes, there is a free running counter from 0 to 4095. > > > And it is probably true, that there can be short intermediate states > > > with our two register writes. > > > > > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > > > which is 0 by default (Outputs change on STOP command) but could be set > > > to 1 (Outputs change on ACK): > > > "Update on ACK requires all 4 PWM channel registers to be loaded before > > > outputs will change on the last ACK." > > > > This would require the auto-increment feature to be enabled, then > > multiple registers could be written before the STOP condition: > > LEDn_ON_L, LEDn_ON_H, LEDn_OFF_L & LEDn_OFF_H > > (With OCH=0 in MODE2) > > Maybe a continued START would work, too?! Yes, maybe. But according to the datasheet bus transaction examples, it's enough to have one START condition and write multiple (continuous) registers using the auto-increment feature. And repeated START does not seem to be supported via regmap..? Clemens
Hello, On Wed, Mar 31, 2021 at 06:21:32PM +0200, Thierry Reding wrote: > However, I'm a bit hesitant about this staggering output mode. From what > I understand what's going to happen for these is basically that overall > each PWM will be running at the requested duty cycle, but the on/off > times will be evenly spread out over the whole period. In other words, > the output *power* of the PWM signal will be the same as if the signal > was a single on/off cycle. That's not technically a PWM signal as the > PWM framework defines it. See the kerneldoc for enum pwm_polarity for > what signals are expected to look like. After reading this thread I had the impression that there is no (externally visible) difference between using ON = 0 plus programming a new setting when the counter is say 70 and using ON = 30 plus programming a new setting when the counter is 100. But that's not the case and I agree that defaulting to staggering is a bad idea. Having said that I doubt that adding a property to the device tree is a good solution, because it changes behaviour without the consumer being aware and additionally it's not really a hardware description. The solution I'd prefer is to change struct pwm_state to include the delay in it. (This would then make the polarity obsolete, because .duty_cycle = 30 .period = 100 .polarity = POLARITY_INVERTED .offset = 0 is equivalent to .duty_cycle = 30 .period = 100 .polarity = POLARITY_NORMAL .offset = 70 . Other inverted states can be modified similarily.) Then consumers can be coordinated to use different offsets. I'm aware changing this isn't trivial, and it's not thought out completely, but I think the end result is rechnically superior to the approach suggested in the patch under discussion. Best regards Uwe
On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote: > On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote: > > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote: > > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote: > > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote: > > > > > The PCA9685 supports staggered LED output ON times to minimize current > > > > > surges and reduce EMI. > > > > > When this new option is enabled, the ON times of each channel are > > > > > delayed by channel number x counter range / 16, which avoids asserting > > > > > all enabled outputs at the same counter value while still maintaining > > > > > the configured duty cycle of each output. > > > > > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> > > > > > > > > Is there a reason to not want this staggered output? If it never hurts I > > > > suggest to always stagger and drop the dt property. > > > > > > There might be applications where you want multiple outputs to assert at > > > the same time / to be synchronized. > > > With staggered outputs mode always enabled, this would no longer be > > > possible as they are spread out according to their channel number. > > > > > > Not sure how often that usecase is required, but just enforcing the > > > staggered mode by default sounds risky to me. > > > > There is no such guarantee in the PWM framework, so I don't think we > > need to fear breaking setups. Thierry? > > Still, someone might rely on it? But let's wait for Thierry's opinion. > > > > > One reason we might not want staggering is if we have a consumer who > > cares about config transitions. (This however is moot it the hardware > > doesn't provide sane transitions even without staggering.) > > > > Did I already ask about races in this driver? I assume there is a > > free running counter and the ON and OFF registers just define where in > > the period the transitions happen, right? Given that changing ON and OFF > > needs two register writes probably all kind of strange things can > > happen, right? (Example thought: for simplicity's sake I assume ON is > > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we > > might see a period with 0xacc. Depending on how the hardware works we > > might even see 4 edges in a single period then.) > > Yes, there is a free running counter from 0 to 4095. > And it is probably true, that there can be short intermediate states > with our two register writes. > > There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"), > which is 0 by default (Outputs change on STOP command) but could be set > to 1 (Outputs change on ACK): > "Update on ACK requires all 4 PWM channel registers to be loaded before > outputs will change on the last ACK." After reading the manual I understood that at least a bit now. The Output chang on STOP is only needed to synchronize two or more PCA9685 chips. Also with "Update on ACK" it is possible to prevent glitches when writing with the auto increment mode. Not sure what happens with the way it is implemented now, as it isn't described in manual when the registers are written in four separate transfers. I agree that addressing this in a separater patch is sensible. Best regards Uwe
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 4d6684b90819..a61eafdd2335 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -78,6 +78,7 @@ struct pca9685 { struct pwm_chip chip; struct regmap *regmap; + bool staggered_outputs; #if IS_ENABLED(CONFIG_GPIOLIB) struct mutex lock; struct gpio_chip gpio; @@ -93,46 +94,70 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip) /* Helper function to set the duty cycle ratio to duty/4096 (e.g. duty=2048 -> 50%) */ static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int duty) { + unsigned int on, off; + if (duty == 0) { /* Set the full OFF bit, which has the highest precedence */ regmap_write(pca->regmap, REG_OFF_H(channel), LED_FULL); + return; } else if (duty >= PCA9685_COUNTER_RANGE) { /* Set the full ON bit and clear the full OFF bit */ regmap_write(pca->regmap, REG_ON_H(channel), LED_FULL); regmap_write(pca->regmap, REG_OFF_H(channel), 0); - } else { - /* Set OFF time (clears the full OFF bit) */ - regmap_write(pca->regmap, REG_OFF_L(channel), duty & 0xff); - regmap_write(pca->regmap, REG_OFF_H(channel), (duty >> 8) & 0xf); - /* Clear the full ON bit */ - regmap_write(pca->regmap, REG_ON_H(channel), 0); + return; } + + if (pca->staggered_outputs && channel < PCA9685_MAXCHAN) { + /* + * To reduce EMI, the ON times of each channel are + * spread out evenly within the counter range, while + * still maintaining the configured duty cycle + */ + on = channel * PCA9685_COUNTER_RANGE / PCA9685_MAXCHAN; + } else + on = 0; + + off = (on + duty) % PCA9685_COUNTER_RANGE; + + /* Set ON time (clears full ON bit) */ + regmap_write(pca->regmap, REG_ON_L(channel), on & 0xff); + regmap_write(pca->regmap, REG_ON_H(channel), (on >> 8) & 0xf); + /* Set OFF time (clears full OFF bit) */ + regmap_write(pca->regmap, REG_OFF_L(channel), off & 0xff); + regmap_write(pca->regmap, REG_OFF_H(channel), (off >> 8) & 0xf); } static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel) { - unsigned int off_h = 0, val = 0; + unsigned int off = 0, on = 0, val = 0; if (WARN_ON(channel >= PCA9685_MAXCHAN)) { /* HW does not support reading state of "all LEDs" channel */ return 0; } - regmap_read(pca->regmap, LED_N_OFF_H(channel), &off_h); - if (off_h & LED_FULL) { + regmap_read(pca->regmap, LED_N_OFF_H(channel), &off); + if (off & LED_FULL) { /* Full OFF bit is set */ return 0; } - regmap_read(pca->regmap, LED_N_ON_H(channel), &val); - if (val & LED_FULL) { + regmap_read(pca->regmap, LED_N_ON_H(channel), &on); + if (on & LED_FULL) { /* Full ON bit is set */ return PCA9685_COUNTER_RANGE; } - val = 0; regmap_read(pca->regmap, LED_N_OFF_L(channel), &val); - return ((off_h & 0xf) << 8) | (val & 0xff); + off = ((off & 0xf) << 8) | (val & 0xff); + if (!pca->staggered_outputs) + return off; + + /* Read ON register to calculate duty cycle of staggered output */ + val = 0; + regmap_read(pca->regmap, LED_N_ON_L(channel), &val); + on = ((on & 0xf) << 8) | (val & 0xff); + return (off - on) & (PCA9685_COUNTER_RANGE - 1); } #if IS_ENABLED(CONFIG_GPIOLIB) @@ -443,14 +468,19 @@ static int pca9685_pwm_probe(struct i2c_client *client, regmap_write(pca->regmap, PCA9685_MODE2, reg); + pca->staggered_outputs = device_property_read_bool( + &client->dev, "nxp,staggered-outputs"); + /* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */ regmap_read(pca->regmap, PCA9685_MODE1, ®); reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3); regmap_write(pca->regmap, PCA9685_MODE1, reg); - /* Reset OFF registers to POR default */ + /* Reset OFF/ON registers to POR default */ regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, LED_FULL); regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, LED_FULL); + regmap_write(pca->regmap, PCA9685_ALL_LED_ON_L, 0); + regmap_write(pca->regmap, PCA9685_ALL_LED_ON_H, 0); pca->chip.ops = &pca9685_pwm_ops; /* Add an extra channel for ALL_LED */
The PCA9685 supports staggered LED output ON times to minimize current surges and reduce EMI. When this new option is enabled, the ON times of each channel are delayed by channel number x counter range / 16, which avoids asserting all enabled outputs at the same counter value while still maintaining the configured duty cycle of each output. Signed-off-by: Clemens Gruber <clemens.gruber@pqgruber.com> --- Changes since v5: - Simplified staggered outputs special case in set/get_duty drivers/pwm/pwm-pca9685.c | 58 +++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 14 deletions(-)