i.MX6 EIM driver for FPGA

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX6 EIM driver for FPGA

Jump to solution
17,861 Views
jamese
Contributor II

I'm currently working on a Linux driver for communicating with a FPGA via the EIM port.  I think I have a handle on the EIM configuration, and the people working on the FPGA are fairly open to how we're doing the communication, so I think we have that covered.  What I don't understand very well, as it's different than anything else I've worked on, is the IOMUX configuration.  I've been digging through the chip reference manual, but it's not giving me a lot of insight into how I set this up. Does anyone have any test code or code snippets they would be willing to share?  Maybe an example they found somewhere that helped?  I've looked through the Linux BSP code, and didn't find anything, but might have missed it.  I would have thought there would be some chipset test code somewhere with the BSP, but it's possible that I missed it.  Thanks.

Labels (3)
1 Solution
3,777 Views
Yuri
NXP Employee
NXP Employee

The SDK may be useful.

https://www.freescale.com/webapp/Download?colCode=i.MX6_PLATFORM_SDK&location=null&fpsp=1&WT_TYPE=La...


Please take a look at Chapter 7 (Configuring the EIM Driver) of "iMX6_Firmware_Guide.pdf"

in SDK docs.

View solution in original post

7 Replies
3,481 Views
ambigersanju
Contributor I

Hi jamese ,

I'm also working on communicating between ARM to FPGA via EIM bus . can you help me with FPGA side ?

1. How you have connected ARM EIM bus to FPGA (ARM Interface in FPGA) ?

2. can the BRAMs in FPGA be Directly Accessed form EIM ?

i am using i.MX6Q and Virtex FPGA.

Thanks in Advance.

Tags (5)
0 Kudos
3,778 Views
Yuri
NXP Employee
NXP Employee

The SDK may be useful.

https://www.freescale.com/webapp/Download?colCode=i.MX6_PLATFORM_SDK&location=null&fpsp=1&WT_TYPE=La...


Please take a look at Chapter 7 (Configuring the EIM Driver) of "iMX6_Firmware_Guide.pdf"

in SDK docs.

3,776 Views
caoping
Contributor II

hi,ereryone!

     now we  are using eim bus,and we use imx535,but we meet some problems in linux,whether we need to configure eim_cfg_t cfg_table or not,thank you!

0 Kudos
3,776 Views
jamese
Contributor II

The SDK does explain some things.  Thank you.  With all the assorted documents I've got, and other bits of software I've gotten off the IMX site, I've not come across this SDK before. 

0 Kudos
3,776 Views
caoping
Contributor II

hi,James

    Now we have used EIM in linux,and we use it to connect CPLD,use iomap to remap phsical base address(0xf0000000) to virtual address, the space is 4MB.we access  the address(the virtual address plus offset address),and we can use  oscilloscope to find nagetive pluse on CS0、WE ane OE signal,but the address line(EIM_A18-EIM_A19) is not act as we want.and we don't know where we are wrong, now we haven't use iomux configuration.

0 Kudos
3,776 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Hello,James,

      This is my personal advice, for you as reference .

      For the usage of WEIM on i.MX6, you don't need drivers for WEIM interface. But you must do some configurations for WEIM port like the following :

      Let me assume you use 16bit Address lines and 16bit Data lines ,CS1 is for FPGA ChipSelect .

Address lines : EIM_DA0~EIM_DA15

Data lines : EIM_D16~EIM_D31

CS1 : Chip Select

(1)IOMUX configurations

All IOMUX settings for sabresd board are in board-mx6q_sabresd.c ,open it and add iomux for address lines ,data lines ,CS1 ,control lines to structure "static iomux_v3_cfg_t mx6q_sabresd_pads[] = {"

static iomux_v3_cfg_t mx6q_sabresd_pads[] = {

....

/*Address Lines*/

MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,

MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,

MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2 ,

MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,

MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,

MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,

MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,

MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,

MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,

MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,

MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,

MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,

MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,

MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,

MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,

MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,

/*Data Lines*/

MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16,

MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17,

MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18,

MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19,

MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_22,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_23,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_24,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_25,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_26,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_27,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_28,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_29,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_30,

MX6Q_PAD_EIM_D21__WEIM_WEIM_D_31,

/*Control Lines*/

MX6Q_PAD_EIM_RW__WEIM_WEIM_RW,// write signal

MX6Q_PAD_EIM_OE__WEIM_WEIM_OE,// read signal

//perhaps following 2 signals are not used.

MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT,// shakehand signal used to sync mode.

MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK,// Burst clock used to burst and sync mode.

MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA,// used to burst mode

/*Chip select line*/

MX6Q_PAD_EIM_CS1__WEIM_WEIM_CS_1,

....

}

(2)Distributing Memory Space For WEIM_CS1

By Defaul,The total 128MB space are all for EIM_CS0,so We should reconfigure space.

In Register IOMUXC_GPR1 ,Bit[5:4] determines address spcace on EIM_CS1

Let us set it 64MB:

bit[5:4] = 01

bit[3]= 1 // Make WEIM_CSI to be Active.

(3)Configuring IOMUX mode

We use 16 bit non-mux mode, So we should configure Register On EIM_CS1. See "Table 22-1. EIM multiplexing" : 16bit,MUM=0,DSZ=010

You should configure EIM_CS1GCR1 register according to the mode that you want. More details , See imx61qrm.pdf , page 1038.

(4)Read/Write Setting

Read:  EIM_CSnRCR1/EIM_CSnRCR2

Write: EIM_CSnWCR1/EIM_CSnWCR2

   Try it on !

Regards,

Weidong

3,776 Views
kartjon
Contributor I

can you help me? I do not know why the EIM do not wor on my board.Pin by the oscilloscope, no change. I config and write EIM like the following:

1.config MUX and PAD

static iomux_v3_cfg_t mx6q_sabresd_pads[] = {

                    .

                    .

                    .

/* eim */

        MX6Q_PAD_EIM_OE__WEIM_WEIM_OE,

        MX6Q_PAD_EIM_RW__WEIM_WEIM_RW,

        MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT,

        MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA,

        MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK,

        MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0,

        /* Data Bus */

        MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16,

        MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17,

        MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18,

        MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19,

        MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20,

        MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21,

        MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22,

        MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23,

        MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24,

        MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25,

        MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26,

        MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27,

        MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28,

        MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29,

        MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30,

        MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31,

        /* Address Bus */

        MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,

        MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,

        MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,

        MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,

        MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,

        MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,

        MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,

        MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,

        MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,

        MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,

        MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,

        MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,

        MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,

        MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,

        MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,

        MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,

};

2.set EIM register

static void mx6q_setup_eim_cs(void)

{

    void __iomem *ram_reg = MX6_IO_ADDRESS(WEIM_BASE_ADDR);

    void __iomem *ccm_reg = MX6_IO_ADDRESS(CCM_BASE_ADDR);

    unsigned int reg;

    struct clk *clk;

    u32 rate;  

    /* CLKCTL_CCGR6: Set emi_slow_clock to be on in all modes */

    reg = readl(ccm_reg + 0x80);

    reg |= 0x00000C00;

    writel(reg, ccm_reg + 0x80);

    clk = clk_get(NULL, "emi_slow_clk");

    if (IS_ERR(clk))

        printk(KERN_ERR "emi_slow_clk not found\n");

    rate = clk_get_rate(clk);

    if (rate != 132000000)

        printk(KERN_ERR "Warning: emi_slow_clk not set to 132 MHz!"

               " WEIM NOR timing may be incorrect!\n");

    writel(0x403304b1, ram_reg);

    writel(0x0, ram_reg + 0x4);

    writel(0x0f010000, ram_reg + 0x8);

    writel(0x00000008, ram_reg + 0xc);

    writel(0x0f040040, ram_reg + 0x10);

    writel(0x00000000, ram_reg + 0x14);

    writel(0x00000000, ram_reg + 0x90);

}

3.iomap(addr:0x08000000, size:0x02000000)

weim->base = devm_ioremap(&pdev->dev, res->start ,len);

            if (weim->base == NULL) {

                    dev_err(&pdev->dev, "Failed to ioremap flash region\n");

                    ret = -EIO;

                    goto weim_err;

            }

4.read and write EIM

long EIM_ioctl(struct file* pFile, unsigned int cmd, unsigned long data)

{

    int val = 0;

    struct eimNode* node = (struct eimNode*)data;

    int *addr = 0; 

    if(weim == 0)

        return FAIL;

    switch(cmd)

    {

    case EIM_READ:

        val = __raw_readl(weim->base + node->offset);

        node->data = val;

        break;

    case EIM_WIRTE:

        __raw_writel(node->data, weim->base + node->offset);

        break;

    default:

        break;

    }

    return SUCCESS;

}

0 Kudos