Re: RPI4 Hardware PWM

From: Matthew Grooms <mgrooms_at_shrew.net>
Date: Tue, 20 Jul 2021 17:30:16 UTC
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