Linux Kernel 4.4 DTS node for Xilinx AXI-DMA IP.

I recently switch to Linux Kernel 4.4 (from 4.0) for some of my projects and to my no surprise found Xilinx AXI-DMA not working again. This time it complained that it can't find DMA channel: "unable to read dma-channels property" and as result "Probing channels failed." So, looks like Xilinx added support for "multi-channel mode" for kernel driver and this is a big deal! And I waited for this forever!

But, as a result of this - DTS node were changed again, braking compatibility. Also, if you using the only one DMA-channel either MM2S or S2MM channel index in your custom DTS node must be 0 in either case, unlike before if you were using only s2mm index was 1 and if only mm2s index was 0.

So, below example of DTS node for AXI DMA and modified xilinx_dmatest(single channel) which works for me for Linux 4.4

axidma0: axidma@40400000 {
        compatible = "xlnx,axi-dma-1.00.a";
        #dma-cells = <1>;
        reg = <0x40400000 0x10000>;
        interrupt-parent = <&intc>;
        dma-channel@40400030 {
                compatible = "xlnx,axi-dma-s2mm-channel";
                dma-channels = <1>;
                interrupts = <0 29 4>;
                xlnx,datawidth = <32>;
                xlnx,include-dre = <0>;
        };
} ;

dmatest0: dmatest@0 {
	compatible ="xlnx,axi-dma-test-1.00.a";
	dmas = <&axidma0 0>;
	dma-names = "axidma1";
};

HDMI on ZedBoard with Petalinux update.

I finally figure it out why Analog Devices reference design create/generated in Vivado 2014 by script(obviously updated to use new IP's, otherwise it didn't assemble 'Block Design' at all) didn't work. Reason is changes in Xilinx Concat IP, which used in reference design to concatenate interrupt signals from VDMA and I2C IP blocks to Zynq's F2S interrupt bus.
So, now in 2014.1, we got version 2.0 of it and it preserve the order of input signals on the output. Which means we must either change inputs order or change interrupt numbers in DTS.

So, for AD reference design generated in Vivado2014.1 interrupts are:

  • AXI_IIC_MAIN - #56.
  • AXI_VDMA_0 - #55.
  • AXI_IIC_FMC - #59.

zynq16_001

HDMI on ZedBoard with Petalinux.

This is step-by-step tutorial on how to build reference design for Analog Devices ADV7511 HDMI encoder used on ZedBoard with PetaLinux 2013.10. It will be mostly based on AD HDL reference design http://wiki.analog.com/resources/fpga/xilinx/kc705/adv7511 and AD Linux drivers wiki page http://wiki.analog.com/resources/tools-software/linux-drivers/platforms/zynq and Xilinx PetaLinux documentation http://www.wiki.xilinx.com/PetaLinux.

As of today, 25 May 2014, to create HDL design for ADV7511 from scratch, we have to use Vivado 2013.4, even though Vivado 2014.1 is already available. The reason is some changes in a Xilinx IP's (which I didn't had a chance to figure out yet) prevent HDL design from build/work properly.

  1. First step is to download HDL libraries and projects from AnalogDevices repositories on a github: https://github.com/analogdevicesinc/hdl. You can clone it or download a ZIP. I will download a ZIP and extract 'hdl-master' in my Projects/FPGA/ folder on Windows7 machine.
  2. Second step is to build a few Analog Devices IP required to create ZedBoard HDMI design. Run Xilinx Vivado 2013.4, open a TCL console, change directories and 'source' a .tcl scripts. For example, to build AXI_CLKGEN IP:

    cd c:/Projects/FPGA/hdl-master/library/axi_clkgen
    source ./axi_clkgen_ip.tcl

    After script finish, close created project and build the next. For ZedBoard we have build the next IP's:

    • hdl-master/library/axi_clkgen
    • hdl-master/library/axi_hdmi_tx
    • hdl-master/library/axi_i2s_adi
    • hdl-master/library/axi_spdif_tx
    • hdl-master/library/util_i2c_mixer
  3. After we done with all required IP's, we can build ADV7511 reference design for ZedBoard. In a Tcl Console change directory to ADV7511 and run 'system_project' script.

    cd c:/Projects/FPGA/hdl-master/projects/adv7511/zed/
    source ./system_project.tcl

    Script will create block design, run synthesis and implementation, generate bitstream and even export software to SDK(without opening it). This was the case on my system - everything went smoothly. We are done with Vivado and can close it.

    We have to create HDL in Vivado 2013.4, but later we can import created project into Vivado 2014.1 and update it to use latest Xilinx IP's.

  4. Let's build a FSBL. We need very typical Zynq first stage boot loader and I covered creation of it before, so now just a short description:
    • Run XSDK.
    • Create new 'Hardware Platform Specification' project (I named it 'ZedBoard-HDMI-HW') and specify HW created in a previous step.
    • Create Application project (named 'ZedBoard-HDMI-FSBL') using our new 'Hardware Platform' and select to create new BSP for it. Don't forget to use 'Zynq FSBL' template. Build it if this not done automatically.
  5. Next step is to create PetaLinux BSP. This is also very typical PetaLinux BSP, just don't forget to change 'Configuration' to reflect ZedBoard configuration and name it 'ZedBoard-HDMI-petalinux_bsp'.

    zynq15_002

    We are done with Xilinx SDK. You can close it.

  6. Next step is to create PetaLinux project and set 'hardware description'. I will call it 'ZedBoard-HDMI' Petalinux project:

    petalinux-create -t project -n ZedBoard-HDMI
    cd ~/Projects/ZedBoard-HDMI-petalinux_bsp/
    petalinux-config --get-hw-description -p ../ZedBoard-HDMI/
    cd ~/Projects/ZedBoard-HDMI/
    rm -r hw-description

  7. Now, as of today, ADV7511 Linux driver not in a mainstream kernel. So, we need to get Kernel from Analog Devices repository with appropriate patches. Current version is 3.14.0. Let's clone it, and checkout 'xcomm_zynq' branch.

    cd ~/Projects/
    git clone https://github.com/analogdevicesinc/linux.git analogdevices-kernel
    cd analogdevices-kernel/
    git checkout xcomm_zynq

  8. Create necessary directories and copy 'xcomm_zynq' branch to our PetaLinux project directory.

    cd ~/Projects/
    mkdir ~/Projects/ZedBoard-HDMI/components
    mkdir ~/Projects/ZedBoard-HDMI/components/linux-kernel
    cp -a analogdevices-kernel ~/Projects/ZedBoard-HDMI/components/linux-kernel/

  9. Run 'petalinux-config' and change kernel to 'analogdevices-kernel' and system boot device to 'SD card'.
  10. cd ZedBoard-HDMI
    petalinux-config

  11. Next we need to configure Linux kernel for PetaLinux and we need to enable all options required by ADV7511. AnalogDevices kernel support special configuration option 'zynq_xcomm_adv7511_defconfig', but we cannot run it with PetaLinux. So, we have to pre-configure kernel separately ('make ARCH=arm zynq_xcomm_adv7511_defconfig') and just copy resulted config into 'ZedBoard-HDMI/subsystems/linux/configs/kernel'. So, I did it and also copied it into PetaLinux Kernel configs directory '/opt/petalinux-v2013.10-final/etc/template/project/template-zynq/subsystems/linux/configs/kernel'. So, I can later reuse it. Also notice that kernel default config file have dot in the front and PetaLinux files don't.
    Anyway, here is link to my resulted kernel config file: https://blog.idv-tech.com/wp-content/uploads/2014/05/config_hdmi_3_14.config
  12. We also, have to modify 'devices tree' generated by PetaLinux for our project. AnalogDecices Linux kernel have template for ZedBoard which you can find in 'arch/arm/boot/dts/zynq-zed-adv7511.dts', so we basically have to copy missing devices from AD into our tree.
    Link to my resulted DTS file for ZedBoard: https://blog.idv-tech.com/wp-content/uploads/2014/05/adv7511_dts.config.
  13. We are basically done. At this point you my want to modify PetaLinux project, for example, include Qt5 library and test app to check frame buffer device later. I covered this topics in my previous post, so I wont repeat it here.

    Build Petalinux project, create BOOT.BIN and copy it together with Linux image file 'image.ub' on SD card:

    petalinux-build
    petalinux-package --boot --fsbl ../ZedBoard-HDMI-FSBL/Release/ZedBoard-HDMI-FSBL.elf --fpga ../ZedBoard-HDMI-HW/system_top.bit --uboot --force -o images/linux/BOOT.BIN

  14. Insert SD card into slot of ZedBoard and turn it on. During boot kernel should detect ADV7511(hdmi) and ADAU1761(sound) devices and create '/dev/fb0' device.So, below partial bootlog from my ZedBoard:
  15. ...
    [drm] Initialized drm 1.1.0 20060810
    /analogdevices-kernel/drivers/gpu/drm/adi_axi_hdmi/axi_hdmi_drv.c:axi_hdmi_platform_probe[176]
    platform 70e00000.axi_hdmi: Driver axi-hdmi requests probe deferral
    ...
    adv7511-hdmi-snd adv7511_hdmi_snd.2: adv7511 <-> 75c00000.axi-spdif-tx mapping ok
    ...
    zed-adau1761-snd zed_sound.3: adau-hifi <-> 77600000.axi-i2s mapping ok
    ...
    Console: switching to colour frame buffer device 180x56
    axi-hdmi 70e00000.axi_hdmi: fb0:  frame buffer device
    axi-hdmi 70e00000.axi_hdmi: registered panic notifier
    [drm] Initialized axi_hdmi_drm 1.0.0 20120930 on minor 0
    /analogdevices-kernel/drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
    ALSA device list:
      #0: HDMI monitor
      #1: ZED ADAU1761
    Freeing unused kernel memory: 23356K (c062b000 - c1cfa000)
    INIT: version 2.88 booting
    Starting Bootlog daemon: bootlogd.
    ...
    
     _____       _           _      _
    | ___ \     | |         | |    (_)
    | |_/ / ___ | |_   __ _ | |     _  _ __   _   _ __  __
    |  __/ / _ \| __| / _` || |    | || '_ \ | | | |\ \/ /
    | |   |  __/| |_ | (_| || |____| || | | || |_| | >  <
    \_|    \___| \__| \__,_|\_____/|_||_| |_| \__,_|/_/\_\
    
    PetaLinux v2013.10 (Yocto 1.4) ZedBoard ttyPS0
    
    ZedBoard login: root
    Password:
    login[923]: root login  on `ttyPS0'
    
    root@ZedBoard:~# ls /dev/fb0
    /dev/fb0
    root@ZedBoard:~# uname -a
    Linux ZedBoard 3.14.0-g681a2d8-dirty #2 SMP PREEMPT Sun May 25 22:46:28 EDT 2014 armv7l GNU/Linux
    root@ZedBoard:~#
    
  16. This is basically it - once you have a framebuffer device you can start using it. So I ran my Qt5 test app and it worked. We obviously don't have any hardware acceleration with this HDL design, but we got basic FB device and HDMI output. Congratulations!

Zynq MMC/SD controller with Linux Kernel 3.12.x and later.

Just a quick note regarding Zynq SD card controller support in Linux Kernel 3.13.x and later. Apparently, Xilinx used industry standard IP blocks for Zynq PS hardware, including SDHC controller. And now they are switching away from 'custom' drivers. For example, Xilinx Zynq PS I2C now called 'Cadence I2C Controller' and new name for Zynq SDHC controller is 'Arasan'.

To make SD card work again with latest kernels, we need to select appropriate option during Linux kernel configuration and make changes for 'ps7_sd_0' and/or 'ps7_sd_1' in devices tree file(DTS). Arasan driver also looking for different 'clock-names'.

Below SD controller section of my DTS file for ZedBoard:

ps7_sd_0: ps7-sdio@e0100000 {
	clock-frequency = <50000000>;
	clock-names = "clk_xin", "clk_ahb";
	clocks = <&clkc 21>, <&clkc 32>;
	compatible = "arasan, sdhci-8.9a";
	interrupt-parent = <&ps7_scugic_0>;
	interrupts = <0 24 4>;
	reg = <0xe0100000 0x1000>;
	xlnx,has-cd = <0x1>;
	xlnx,has-power = <0x0>;
	xlnx,has-wp = <0x1>;
} ;

zynq12_001