Two drivers are provided by Atmel in the Kernel mainstream to generate the PWM signals
These drivers exposes a sysfs user space interface to manage the PWM signals.
Device Drivers --->
[*] Pulse-Width Modulation (PWM) Support --->
<*> Atmel TC Block PWM support
The PWM sysfs at startup interface will create a directory called /sys/class/pwm/pwmchip0.
For any PWM line you want to use you have to export it.
~# echo 0 > /sys/class/pwm/pwmchip0/export ~# echo 1 > /sys/class/pwm/pwmchip0/export ~# echo 2 > /sys/class/pwm/pwmchip0/export ~# echo 3 > /sys/class/pwm/pwmchip0/export ...
To use again that line ad generic GPIO you can unexport it:
~# echo 0 > /sys/class/pwm/pwmchip0/unexport ~# echo 1 > /sys/class/pwm/pwmchip0/unexport ~# echo 2 > /sys/class/pwm/pwmchip0/unexport ~# echo 3 > /sys/class/pwm/pwmchip0/unexport ...
For any exported channel a directory called pwmX wil be created with the following structure:
/sys/class/pwm/pwmchip0/pwmX/ |-- duty_cycle (r/w) duty cycle (in nanoseconds) |-- enable (r/w) enable/disable PWM |-- period (r/w) period (in nanoseconds) |-- polarity (r/w) polarity of PWM |-- power `-- uevent
The follow example illustrate how enable a PWM signale with a period of 1mS with a 0.5mS of duty cycle:
~# echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period ~# echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle ~# echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
pwm0: pwm@f002c000 {
pinctrl-names = "default";
pinctrl-0 = <
&pinctrl_pwm0_pwmh0
&pinctrl_pwm0_pwml0
&pinctrl_pwm0_pwmh1
&pinctrl_pwm0_pwml1
&pinctrl_pwm0_pwmh2
&pinctrl_pwm0_pwml2
&pinctrl_pwm0_pwmh3
&pinctrl_pwm0_pwml3
>;
status = "okay";
};
pinctrl@fffff200 {
board {
pinctrl_pwm0_pwmh0: pwm0_pwmh0 {
atmel,pins =
< AT91_PIOB 0 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwml0: pwm0_pwml0 {
atmel,pins =
< AT91_PIOB 1 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwmh1: pwm0_pwmh1 {
atmel,pins =
< AT91_PIOB 4 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwml1: pwm0_pwml1 {
atmel,pins =
< AT91_PIOB 5 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwmh2: pwm0_pwmh2 {
atmel,pins =
< AT91_PIOB 8 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwml2: pwm0_pwml2 {
atmel,pins =
< AT91_PIOB 9 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwmh3: pwm0_pwmh3 {
atmel,pins =
< AT91_PIOB 12 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
pinctrl_pwm0_pwml3: pwm0_pwml3 {
atmel,pins =
< AT91_PIOB 13 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
};
};
pinctrl@fffff400 {
pwm0 {
pinctrl_pwm0: pwm0-0 {
atmel,pins =
< AT91_PIOC 18 AT91_PERIPH_C AT91_PINCTRL_NONE
AT91_PIOC 19 AT91_PERIPH_C AT91_PINCTRL_NONE
AT91_PIOC 20 AT91_PERIPH_C AT91_PINCTRL_NONE
AT91_PIOC 21 AT91_PERIPH_C AT91_PINCTRL_NONE >;
};
};
};
pwm0: pwm@f8034000 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm0>;
status = "okay";
};
pinctrl@fffff400 {
pwm0 {
pinctrl_pwm0: pwm0-0 {
atmel,pins =
< AT91_PIOB 11 AT91_PERIPH_B AT91_PINCTRL_NONE
AT91_PIOB 12 AT91_PERIPH_B AT91_PINCTRL_NONE
AT91_PIOB 13 AT91_PERIPH_B AT91_PINCTRL_NONE
AT91_PIOB 14 AT91_PERIPH_B AT91_PINCTRL_NONE >;
};
};
};
Many thanks to Nicolas Ferre and Boris Brezillon for their help.