Why do I want this?

I use the pwm-ir-tx kernel module to blast IR signals from my embedded device. However, when the pwm kernel module is loaded during the boot process, the pin is on high. It takes about 10 seconds or so until I can set it to low with a lirc irsend signal. You can in principle 'overload' the IR-LED to make it brighter, if it is only used in PWM mode and not permanently on. The 10 seconds during the boot process undermine this strategy, however.

What is my system doing so far (e.g. what's working, DT-Overlay file, etc)?

I am using Armbian and modified the pwm-ir-tx driver in the mainline kernel, so that the state after a send is guaranteed low (setting duty cycle to 0, it was randomly 1 or 0 when just disabling the pwm channel on my device).

I am using a device tree overlay that activates the pwm and the pwm-ir-tx.


/ {
    compatible = "allwinner,sun4i-a10";

    fragment@0 {
        target = <&pwm>;
        __overlay__ {
            pinctrl-names = "default";
            pinctrl-0 = <&pwm0_pin>, <&pwm1_pin>;
            status = "okay";

    fragment@1 {
        target-path = "/";
        __overlay__ {
            pwm-ir-transmitter {
                compatible = "pwm-ir-tx";
                pwms = <&pwm 0 0 0>;


When I boot, the pwm-sun4i modules and pwm-ir-tx are loaded and a /dev/lircx character device is available to be used. To turn the LED off, I enabled a systemd service 'lircd-out' with the Unit entry 'After=lircd.service', that turns the led off, but it runs about 10 seconds after the boot process.

Setting modules in the DT Overlay to "disabled" and loading them with modprobe afterwards is not working (not creating pwm or rc devices in sysfs, or a /dev/lircx character device). Maybe since those modules are built in (i.e. configured with 'Y', not 'M' in the .config file), but I must admit my understanding is still a bit fuzzy, here.

What would be ideal?

The ability to control the loading of the modules pwm-sun4i and pwm-ir-tx and thus be able to run a script after pwm-sun4i was loaded that sets the pwm pin to low and then load pwm-ir-tx. But as I mentioned, when I load those modules manually, they are somehow not accessible for the sysfs.

Alternatively, I could pass a parameter in the fragment@0 to the pwm that sets it to low. But I do not know how and do not see anything in the code of pwm-sun4i.c that would allow this. I do not want to modify the kernel source to keep it compatible for updates.

Any suggestions?


Create an udev rule to match it.

It shouldn't be necessary to run the script "after a module is loaded" – it deals with a specific device, so it would be better to run it "after the device is detected". Doesn't matter how the device was detected; as long as the kernel reports it as a 'new' device, it'll work.

That said, modules have a presence in /sys just like devices, which means they too can trigger udev rules, and even have systemd .device units generated for them.

For example, to trigger a service as soon as pwm-sun4i loads, use this udev rule:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="pwl-sun4i", \
    TAG+="systemd", ENV{SYSTEMD_WANTS}+="fixup-pwl.service"

To run a simple oneshot command:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="pwl-sun4i", RUN+="/etc/fix-pwl.sh"
  • The solution worked in principle and answered the question. However, to solve the problem, I had to use a different strategy. Pwm is made accessible in user space through a class in sysfs. Device detection also worked, but I could not do anything to pwm neither before the module pwm-sun4i was loaded nor after the channel was claimed by pwm-ir-tx module. I therefore modified the pwm-ir-tx module so that the pins are set to low immediately after the pwm-ir-tx module claims the pwm channel. – user3117071 Apr 24 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.