Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Jun 2019 08:16:06 -0600
From:      Ian Lepore <ian@freebsd.org>
To:        Nicola Mingotti <nmingotti@gmail.com>, Sergey Manucharian <sm@ara-ler.com>
Cc:        nmingott@gmail.com, freebsd-arm@freebsd.org
Subject:   Re: How to set PWM tunable name to ehrpwm.1 ?
Message-ID:  <8237753a486d20599815aa869eb729433c03eb8b.camel@freebsd.org>
In-Reply-To: <f1e1609d-beba-1d49-faf0-ba470c00a773@gmail.com>
References:  <68790975-a5a5-2138-ca89-117878d6cf2d@gmail.com> <20190606220639.GE13546@eldorado> <8126fa4ae0ca650ca12f28dd538e6e8c4e81b432.camel@freebsd.org> <2852b9da-e647-69a7-3218-88cfa500eadc@gmail.com> <ee540fb38eca660a722f561fc91b660560133ed5.camel@freebsd.org> <f1e1609d-beba-1d49-faf0-ba470c00a773@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 2019-06-07 at 10:23 -0700, Nicola Mingotti wrote:
> 
> On 6/7/19 7:58 AM, Ian Lepore wrote:
> > [...]
> > > 
> > > 
> > 
> > The dev.* hierarchy is managed by newbus; what I was picturing was
> > something like hw.ehrpwm1.freq and so on, settable as either tunable or
> > sysctl.  But it turns out ehrpwm1 is just a label in the dts, not
> > accessible at runtime.  The actual node name is just 'pwm' and really,
> > nothing prevents upstream from changing that name on a whim next time
> > we import new dts files.  (And linux sure seems to have a lot of
> > arbitrary whims when it comes to changing dts.)
> > 
> > Since an overlay is required to use this stuff anyway, I'm now thinking
> > a custom property in the overlay that names the sysctl nodes might be a
> > good option.  So you'd add a property like:
> > 
> >     &ehrpwm0 {
> >         status = "okay";
> >         pinctrl-names = "default";
> >         pinctrl-0 = <&ehrpwm0_AB_pins>;
> >         freebsd,sysctl = "backlight";
> >     };
> > 
> > And that would make it install names like hw.backlight.freq and
> > hw.backlight.period and so on.  If you don't add that property, it just
> > installs the names it uses now (dev.ehrpwm.*) for compatibility.
> > 
> > -- Ian
> > 
> > 
> 
> Ian, this |freebsd,sysctl = "foobar"| to me sounds as a very good solution.
> 
> In this way I could name the tunable with the "hardware name" or also 
> with the functional name, as "pwm-motor-front-left". This would improve 
> the readability of underlying software structure. That would be beautiful.
> 
> n.
> 

I just realized I never followed up on this thread after doing the
work.

After talking to Manu on irc about this, we decided the right way to go
was to use the pwm(9) kernel api and the pwm(8) userland tool for
controlling pwm devices, instead of just extending the ad-hoc sysctl
scheme in the TI driver.  I reworked the pwm(9) api a bit to support
the idea of "named channels", then added support for pwm(9) to the
ti_ehrpwm driver.  All of that work was done in 13-current and has now
been merged to 12-stable; it should be available in the next weekly-
build snapshots for beaglebone.

To use the new stuff... if you build custom kernels, you can add
'device pwmbus' and 'device pwmc' to your kernel config.  Or, you can
load those devices as modules.  On -current the modules will get auto-
loaded by devd as needed; I'm not sure if that works in 12-stable or
not.  The other thing you need to do is apply a dts overlay to enable
the pwm hardware, setup the pinmux, and define the names for the
channels.  Here's the dtso I used for testing (based on the one you
posted earlier in this thread, but with the freebsd,pwmc nodes added):

/dts-v1/;
/plugin/;

/ {
    compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
    exclusive-use = "P9.21","P9.22","ehrpwm0_AB";
};

&am33xx_pinmux {
    ehrpwm0_AB_pins: pinmux_ehrpwm0_AB_pins {
        pinctrl-single,pins = <
            0x154 0x03 /* P9.21 */
            0x150 0x03 /* P9.22 */ 
        >;
    };
};

&ehrpwm0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&ehrpwm0_AB_pins>;

    pwmcontrol@0 {
        compatible = "freebsd,pwmc";
        reg = <0>;
        label = "backlight";
    };

    pwmcontrol@1 {
        compatible = "freebsd,pwmc";
        reg = <1>;
	label = "ChannelB";
    };
};

&epwmss0 {
    status = "okay";
};

&ecap0 {
    status = "okay";
};

The pwmc(4) driver creates nodes in /dev/pwm/ named pwmcX.Y where X is
the unit number and Y is the channel number within that unit.  As usual
the unit number may change depending on which devices are present, so
the dts can include a label= property and the driver creates an alias
for the pwmcX.Y with that name:

 ll /dev/pwm
 [...] root  wheel       14 Jun 29 13:54 ChannelB@ -> ../pwm/pwmc0.1
 [...] root  wheel       14 Jun 29 13:54 backlight@ -> ../pwm/pwmc0.0
 [...] root  operator  0x5f Jun 29 13:54 pwmc0.0
 [...] root  operator  0x5d Jun 29 13:54 pwmc0.1

With this in place, you can use the pwm(8) tool for control.  It takes
period and duty cycle in nanoseconds, or duty as a percentage.  For
example, to set the 'ChannelB' output to a 100KHz signal with 40% duty
cycle and enable it:

 pwm -f /dev/pwm/ChannelB -E -p 10000 -d 40%

To change it to 1ms on, 1ms off (it stays enabled):

 pwm -f /dev/pwm/ChannelB -p 2000000 -d 1000000

There are manpages for the pwmc(4) device (describes the dts format)
and the pwm(8) tool.  If you are writing your own custom C code for
control, you can use ioctl() calls for pwm control; the pwmc(4) manpage
details that stuff too.

-- Ian




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?8237753a486d20599815aa869eb729433c03eb8b.camel>