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.
解決済! 解決策の投稿を見る。
The SDK may be useful.
Please take a look at Chapter 7 (Configuring the EIM Driver) of "iMX6_Firmware_Guide.pdf"
in SDK docs.
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.
The SDK may be useful.
Please take a look at Chapter 7 (Configuring the EIM Driver) of "iMX6_Firmware_Guide.pdf"
in SDK docs.
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!
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.
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.
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
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;
}