Re: RPI4 Hardware PWM

From: Ian Lepore <ian_at_freebsd.org>
Date: Tue, 20 Jul 2021 18:12:41 UTC
On Tue, 2021-07-20 at 12:30 -0500, Matthew Grooms wrote:
> On 6/11/2021 9:21 AM, Matthew Grooms wrote:
> > On 6/11/2021 9:19 AM, Matthew Grooms wrote:
> > > On 6/9/2021 4:16 PM, Matthew Grooms wrote:
> > > > On 6/8/2021 4:06 PM, Matthew Grooms wrote:
> > > > > Hey All,
> > > > > 
> > > > > I have a project I'm working on that depends on interfacing
> > > > > with a 
> > > > > few sensor modules using both i2c and PWM. I've got the i2c
> > > > > devices 
> > > > > to work correctly, but I'm not sure how to interface with the
> > > > > HW 
> > > > > PWM support of the RPI4. I can see there are settings exposed
> > > > > via 
> > > > > sysctl for Beaglebone systems ...
> > > > > 
> > > > > https://zewaren.net/bbb-pwm.html
> > > > > 
> > > > > I was hoping I'd be able to force GPIO 12 or 13 into ALT0 and
> > > > > set 
> > > > > the duty values via sysctl, but that doesn't seem to be an
> > > > > option. 
> > > > > Any help would be greatly appreciated.
> > > > 
> > > > Replying to myself with a bit more info. I see that there is a 
> > > > driver available for rpi boards authored by PHK ...
> > > > 
> > > > 
https://cgit.freebsd.org/src/tree/sys/arm/broadcom/bcm2835/bcm2835_pwm.c
> > > >  
> > > > 
> > > > 
> > > > That has notes on RPi2/3 boards, but not mention of RPi4. When
> > > > I 
> > > > load that, I see the following output ...
> > > > 
> > > > Jun  9 18:29:50 generic kernel: pwm0: <BCM2708/2835 PWM
> > > > controller> 
> > > > mem 0x7e20c000-0x7e20c027 on simplebus0
> > > > Jun  9 18:29:50 generic kernel: pwm0: cannot find Clock Manager
> > > > 
> > > > I assume I'm doing something wrong. Any feedback would be
> > > > greatly 
> > > > appreciated.
> > > 
> > > Hey Everyone,
> > > 
> > > I decided to take a look at the patch that introduced rpi4
> > > support in 
> > > Linux. I'm pretty out of my depth here but they didn't look all
> > > that 
> > > extensive. One obvious difference that stood out was that the
> > > FreeBSD 
> > > clock manager driver only appears to load for the bcm2835 part
> > > while 
> > > the Linux driver loads for both 2835 and 2711. Adding the
> > > following 
> > > line to the clkman driver allows the pwm driver to load without
> > > an 
> > > error now ...
> > > 
> > > --- bcm2835_clkman.c    2021-06-11 09:06:19.893728000 -0500
> > > +++ bcm2835_clkman.c    2021-06-11 08:50:44.646221000 -0500
> > > @@ -51,6 +51,7 @@
> > >  #include <arm/broadcom/bcm2835/bcm2835_clkman.h>
> > > 
> > >  static struct ofw_compat_data compat_data[] = {
> > > +       {"brcm,bcm2711-cprman",         1},
> > >         {"brcm,bcm2835-cprman",         1},
> > >         {"broadcom,bcm2835-cprman",     1},
> > >         {NULL,                          0}
> > > 
> > > root@generic:/home/mgrooms # tail -n 1 /var/log/messages
> > > Jun 11 08:35:58 generic kernel: pwm0: <BCM2708/2835 PWM
> > > controller> 
> > > mem 0x7e20c000-0x7e20c027 on simplebus0
> > > 
> > > Additionally, there appears to be valid sysctl values for the 
> > > hardware pwm devices now. I'll try testing them out and see if I
> > > can 
> > > determine if they're working as expected and report back.
> > 
> > Woops. I was going to include these for reference:
> > 
> > root@generic:/home/mgrooms # sysctl -a | grep pwm
> > dev.pwm.0.mode2: 0
> > dev.pwm.0.ratio2: 2500
> > dev.pwm.0.period2: 10000
> > dev.pwm.0.pwm_freq2: 0
> > dev.pwm.0.mode: 0
> > dev.pwm.0.freq: 125000000
> > dev.pwm.0.ratio: 2500
> > dev.pwm.0.period: 10000
> > dev.pwm.0.pwm_freq: 0
> > dev.pwm.0.%parent: simplebus0
> > dev.pwm.0.%pnpinfo: name=pwm@7e20c000 compat=brcm,bcm2835-pwm
> > dev.pwm.0.%location:
> > dev.pwm.0.%driver: pwm
> > dev.pwm.0.%desc: BCM2708/2835 PWM controller
> > dev.pwm.%parent:
> > 
> 
> Hey everyone. I just wanted to follow up on this. I can confirm that 
> with that one line patch, hardware pwm appears to be working reliably
> on 
> my rpi4b. Since I struggled to find man pages that explain what
> these 
> values do ( maybe just missed a man page? ), here are some notes I
> took:
> 
> /sbin/sysctl dev.gpio.0.pin.12.function=alt0    # set pin to hw pwm
> function
> /sbin/sysctl dev.pwm.X.mode=1                   # 0 = off | 1 = on
> /sbin/sysctl dev.pwm.X.freq=1000000             # clock frequency
> /sbin/sysctl dev.pwm.X.period=1000              # pwm_freq = freq /
> period
> /sbin/sysctl dev.pwm.X.ratio=500                # 0 - period = 0 -
> 100% 
> duty cycle
> 
> dev.pwm.0.mode2: 0
> dev.pwm.0.ratio2: 2500
> dev.pwm.0.period2: 10000
> dev.pwm.0.pwm_freq2: 0
> dev.pwm.0.mode: 1
> dev.pwm.0.freq: 1000000
> dev.pwm.0.ratio: 0
> dev.pwm.0.period: 1000
> dev.pwm.0.pwm_freq: 1000
> dev.pwm.0.%parent: simplebus0
> dev.pwm.0.%pnpinfo: name=pwm@7e20c000 compat=brcm,bcm2835-pwm
> dev.pwm.0.%location:
> dev.pwm.0.%driver: pwm
> dev.pwm.0.%desc: BCM2708/2835 PWM controller
> dev.pwm.%parent:
> 
> For the above example: A ratio value of 0 would be a 0% duty cycle,
> 500 
> would be 50% and 1000 would be 100%. Hopefully this helps someone
> else 
> in the future.
> 
> -Matthew
> 

The documentation problem comes from the fact that the rpi pwm driver
was written before pwmbus and pwm(8) came along; those are the ones
that are documented.  The rpi driver really should be changed to fit
into the newer pwmbus architecture.  But the rpi code doesn't have much
in the way of active mantainers.

-- Ian