This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Accessing EMIF bus from User Space Keystone II EVM

Other Parts Discussed in Thread: OMAPL138

I am fairly new to Linux especially to device drivers but I come from the world of porgramming microcontrollers or microprocessors with no operating system or memory management system running on them. I am using the Keystone II processor on the TCI6638K2K EVM and am trying to add read/write functionality to a new device on the EMIF bus. Currently the Linux Kernel only has one registered and it is the NAND flash memory that the board boots from. I would like to set up another device (and FPGA) using a separate chipselect that can be read and written too from my userspace application. I am wondering what to do to get started. I have started by adding a new node in the device tree that should set up the proper registers in the driver but am lost on how I will communicate either with the driver or with the devices memory. I am familiar with the difference between virtual and physical memory so I have tried to mmap() the EMIF register sections to virtual memory in my userspace code but get a segmentation fault every time. Thanks for all your help.

  • Hi William,

    Please provide below information.

    1. EVM Board revision.

    2. EMIF CS(Chip Select) number for FPGA interfacing.

    3. Modified driver/dtb file

    4. Return value of mmap() 

    Thanks.

  • Hi William,

    Have you read the Linux documentation about the driver from below link?

    http://processors.wiki.ti.com/index.php/MCSDK_UG_Chapter_Exploring#AEMIF_Driver

    Thanks.

  • The EVM revision I am using is A1.

    The CS i am trying to use is CS1 (CE3)

    Here is the aemif section of the modified .dtb (The bold is what I added it is a copy of the cs for nand)  

    aemif@30000000 {
       compatible = "ti,davinci-aemif";
       #address-cells = <0x2>;
       #size-cells = <0x1>;
       reg = <0x21000a00 0x100>;
       ranges = <0x2 0x0 0x30000000 0x8000000 0x3 0x0 0x34000000 0x4000000 0x4 0x0 0x38000000 0x4000000 0x5 0x0 0x3c000000 0x4000000 0x6 0x0 0x21000a00 0x100>;
       clocks = <0x11>;
       clock-names = "aemif";

       cs2@30000000 {
        compatible = "ti,davinci-cs";
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        ti,davinci-cs-ta = <0xc>;
        ti,davinci-cs-rhold = <0x6>;
        ti,davinci-cs-rstrobe = <0x17>;
        ti,davinci-cs-rsetup = <0x9>;
        ti,davinci-cs-whold = <0x8>;
        ti,davinci-cs-wstrobe = <0x17>;
        ti,davinci-cs-wsetup = <0x8>;
       };

       nand@2,0 {
        compatible = "ti,davinci-nand";
        reg = <0x2 0x0 0x8000000 0x6 0x0 0x100>;
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        ti,davinci-chipselect = <0x0>;
        ti,davinci-mask-ale = <0x2000>;
        ti,davinci-mask-cle = <0x4000>;
        ti,davinci-mask-chipsel = <0x0>;
        ti,davinci-ecc-mode = "hw";
        ti,davinci-ecc-bits = <0x4>;
        ti,davinci-nand-use-bbt;
        ti,davinci-no-subpage-write;
        clocks = <0x11>;
        clock-names = "aemif";

        partition@0 {
         label = "u-boot";
         reg = <0x0 0x100000>;
         read-only;
        };

        partition@100000 {
         label = "params";
         reg = <0x100000 0x80000>;
         read-only;
        };

        partition@180000 {
         label = "ubifs";
         reg = <0x180000 0x1fe80000>;
        };
        
        
       };
       
       cs3@34000000 {
        compatible = "ti,davinci-cs";
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        ti,davinci-cs-asize = <0x1>;
        ti,davinci-cs-ta = <0xc>;
        ti,davinci-cs-rhold = <0x6>;
        ti,davinci-cs-rstrobe = <0x17>;
        ti,davinci-cs-rsetup = <0x9>;
        ti,davinci-cs-whold = <0x8>;
        ti,davinci-cs-wstrobe = <0x17>;
        ti,davinci-cs-wsetup = <0x8>;
       };
       
      };

     

     

    I found out why my mmap was returning segmentation fault, it was because I has the wrong address in it. Now it is returning an address which changed everytime (I assume because this is virtual memory) but I am still not sure where I go from her in terms of reading and writing to the FPGA.

    Here is my mmap() call:

    off_t    dev_base = 0x34000000;

    size_t    ldev = 0x4000;

    memfd = open("/dev/mem", O_RDWR | O_SYNC);

    memfd = open("/dev/mem", O_RDWR | O_SYNC);

    mapped_base =(int*)mmap(0, ldev, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, dev_base);=

    if (mapped_base == MAP_FAILED)

    {

    errx(1,"mmap failure");

    }

  • Hi William,

    I am working on your query, will post my suggestion early next week.

    Thank you for your patience.

  • Hi William,

    Have you ensured that the chip select initialization is passed?

    file: drivers/memory/davinci-aemif.c

    function: of_davinci_aemif_parse_abus_config()

    static int of_davinci_aemif_parse_abus_config(struct device_node *np)
    {
            struct davinci_aemif_cs_data *data;
            unsigned long cs;
            int val;
    
            if (kstrtoul(np->name + 2, 10, &cs) < 0)
                    return -EINVAL;
    
            if (cs < 2 || cs >= NUM_CS)
                    return -EINVAL;
    
            if (aemif->cfg->num_cs >= NUM_CS)
                    return -EINVAL;
    .
    .
    .
    .
    .
    }


    Please provide EVM revision as specified in the below site. The revision info shall be found in EVM's connector.

    http://www.advantech.com/Support/TI-EVM/EVMK2HX.aspx

    Thanks.

  • Ok I now see that I have revision 2.0. I am unsure if the chip select initialization has passed since this is running in the kernel but I can see a directory called cs3.3 created in

    /sys/bus/platform/devices/21000a00.aemif

    so I assume it is being created. Does the creation of a new CS device just open up memory mapped space to the device on the EMIF bus or do I write and read to a buffer like in an i2c or spi interface? Is all I need to do is mmap() a section of memory @ 0x34000000? I guess this is what has been confusing me.

  • Hi William,

    As per my understanding, 

    • The above dts file changes should initialize the required timing parameters for the selected chip select. Ensure the timing parameters are right.
    • You need another kernel driver or user space(mmap) driver to access the chip select regions. I think you are doing right here.

    Have you ensured that the FPGA is interfaced correctly? How the FPGA code is validated?

    Thanks.

  • This is great. Thank you. I guess I just need to spend some time debugging my code. I was just a little unfimiliar with device trees/drivers and how to access the address space. I think I have gotten some good information now about it by googling mmap. If I get it working I will post my solution back here. Thank you.

  • Hi William,

    That sounds good! Please keep us posted and let us know if you have any queries. Thanks.

  • HI Rajasekaran K,

    I am working on accesses  fpga via emif interface on Linux code. I couldn't find complete solution on this topic in this forum.

    Do you have similar information you post here for omapl138? I searched my psp/ that has no such davinci-aemif.c.

    it includes a aemif.c, but has no function that you mentioned here.


    Or do you know that if TI has documented this topic in some where for developer to follow.

    Thank you

    Joe

     

  • Hi Joe,

    Can you please create a new thread for this issue as posting on the same thread will get only less attention when compared to the new one.

    Please refer the following thread.

    http://e2e.ti.com/support/embedded/linux/f/354/t/122942.aspx