Xilinx PWM controller
This driver is provided as is. No guarantee. Tested on zedboard.
This driver works together with the Xilinx Axi timer hardware core. The core is available for the microblaze and Arm based Xilinx platforms.
The axi timer core is implemented in the pl (programmable logic) of the fpga. The amount is user defined. Each core has two timers and one pwm output.
After genereating the design and bitstream, you have to use the Xilinx device tree generator (git://git.xilinx.com/device-tree.git) to generate the dts file or the petalinux tools (http://www.xilinx.com/tools/petalinux-sdk.htm).
Within this dts file, you find the axi-timer and clock definitions.
axi_timer_0: timer@42800000 {
clock-frequency = <100000000>;
compatible = "xlnx,axi-timer-2.0", "xlnx,xps-timer-1.00.a";
reg = <0x42800000 0x10000>;
xlnx,count-width = <0x20>;
xlnx,gen0-assert = <0x1>;
xlnx,gen1-assert = <0x1>;
xlnx,one-timer-only = <0x0>;
xlnx,trig0-assert = <0x1>;
xlnx,trig1-assert = <0x1>;
} ;
...
ps7_slcr_0: ps7-slcr@f8000000 {
compatible = "xlnx,ps7-slcr-1.00.a", "xlnx,zynq-slcr";
reg = <0xf8000000 0x1000>;
clocks {
#address-cells = <1>;
#size-cells = <0>;
clkc: clkc {
#clock-cells = <1>;
clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x", "cpu_3or2x",
"cpu_2x", "cpu_1x", "ddr2x", "ddr3x", "dci",
"lqspi", "smc", "pcap", "gem0", "gem1",
"fclk0", "fclk1", "fclk2", "fclk3", "can0",
"can1", "sdio0", "sdio1", "uart0", "uart1",
"spi0", "spi1", "dma", "usb0_aper", "usb1_aper",
"gem0_aper", "gem1_aper", "sdio0_aper", "sdio1_aper", "spi0_aper",
"spi1_aper", "can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper",
"uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper", "smc_aper",
"swdt", "dbg_trc", "dbg_apb";
compatible = "xlnx,ps7-clkc";
fclk-enable = <0xf>;
ps-clk-frequency = <33333333>;
} ;
} ;
} ;
Some required properties should be changed
- compatible: should be "xlnx,pwm-xlnx"
- add the right clock source to the description - clocks = <&clkc 15>; - is fclk0 in this design
- add #pwm-cells = <2>;
Examples:
axi_timer_0: timer@42800000 {
clock-frequency = <100000000>;
#pwm-cells = <2>;
clocks = <&clkc 15>;
compatible = "xlnx,xlnx-pwm";
reg = <0x42800000 0x10000>;
xlnx,count-width = <0x20>;
xlnx,gen0-assert = <0x1>;
xlnx,gen1-assert = <0x1>;
xlnx,one-timer-only = <0x0>;
xlnx,trig0-assert = <0x1>;
xlnx,trig1-assert = <0x1>;
} ;
Generate the dtb file and load it on the target platform.
Compile the pwm drivers as module or in the kernel. cp pwm-xlnx.c into the drivers/pwm/pwm folder and change the Kconfig and Makefile. You can also patch the pwm-xlnx.patch file (I'm using kernel 3.14 in the xilinx-tree).
The driver will register all the hardware timers, signed by compatible = "xlnx,xlnx-pwm"
/sys/class/pwm/pwmchip0
/sys/class/pwm/pwmchip1
/sys/class/pwm/pwmchip2
/sys/class/pwm/pwmchip3
echo 0 > /sys/class/pwm/pwmchip0/export
cd /sys/class/pwm/pwmchip0/pwm0/
echo 100000 > period //period is 100us
echo 30000 > duty_cycle //duty_cycle of 30 us
echo 1 > enable