背景:公司现有的开发板内核没有EIM总线驱动,在百度上找了一下文章都说很简单,驱动一配什么的就好了,自己做了一份,通过FPGA查看,各个引脚均无反应。。。前一阵,发现飞凌开发板提供了该驱动,于是便搞了一套。。。
ARM平台:iMX6Q
Linux版本:3.0.35
1、将driver\misc\fpga.c文件拷贝到现有内核同路径文件夹下,同时修改Makefile文件,编译时自动编入内核;
obj-y += fpga.o
2、在arch/arm/mach-mx6/board-mx6q_xxxx.h中增加weim引脚定义
static iomux_v3_cfg_t mx6q_weimram_pads[] __initdata = {
/* Parallel NOR */
MX6Q_PAD_EIM_OE__WEIM_WEIM_OE,
MX6Q_PAD_EIM_RW__WEIM_WEIM_RW,
MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0,
// MX6Q_PAD_EIM_EB0__WEIM_WEIM_EB_0,
MX6Q_PAD_EIM_EB1__WEIM_WEIM_EB_1,
MX6Q_PAD_EIM_EB2__WEIM_WEIM_EB_2,
MX6Q_PAD_EIM_EB3__WEIM_WEIM_EB_3,
/*Control NOR reset using gpio mode*/
//MX6Q_PAD_DISP0_DAT8__GPIO_4_29,
MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA,
MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
/* Parallel Nor 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,
/* Parallel Nor 25 bit Address Bus */
/* Parallel Ram 19 bit Address Bus */
//MX6Q_PAD_EIM_A24__GPIO_5_4,
MX6Q_PAD_EIM_A25__WEIM_WEIM_A_25,//bs add
MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24,//bs add
MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23,
MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22,
MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21,
MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20,
MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19,
MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18,
MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17,
MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16,
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,
};
3、在arch/arm/mach-mx6/board-mx6q_xxxx.c中增加相关设备定义函数
static int mx6q_setup_weim_cs(void)
static int mx6q_setup_weim_cs(void)
{
//nor
void __iomem *ram_reg = MX6_IO_ADDRESS(WEIM_BASE_ADDR);//EIM memory base phy addr=0x21B8000
void __iomem *ccm_reg = MX6_IO_ADDRESS(CCM_BASE_ADDR);
unsigned int reg;
struct clk *clk;
u32 rate;
/*iomuxc_gpr1 cs0 cs1 cs2 cs3 set*/
//reg = readl(IOMUXC_GPR1);
//printk("gpr1 reg=%x\n",reg);
/* 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);
//printk("emi_slow_clk rate=%d\n",rate);
if(rate!=132000000)
printk(KERN_ERR "Warning: emi_slow_clk not set to 132 MHz!"
" WEIM NOR timing may be incorrect! rate %d \n", rate);
//rate=clk_round_rate(clk,264000000);//37MHZ
//clk_set_rate(clk,rate);
printk("emi_slow_clk rate=%d\n",rate);
clk_put(clk);
/*
CS0GCR1:
GBC=0;CSREC=1;DSZ=2;BL=0;
CREP=1;CSEN=1;
Operation Mode: MUM=SRD=SWR=0.
(Async write/Async page read,none multiplexed)
*/
writel(0x00020081, ram_reg);//EIM_CS0GCR1
/*
ADH=0
*/
writel(0x00000000, ram_reg + 0x4); //EIM_CS0GCR2
/*
CS0RCR1:
RWSC=1;//28
RADVA=0;RADVN=0;
OEA=0;OEN=0;
RCSA=0;RCSN=0;
*/
writel(0x01080000, ram_reg + 0x8);//EIM_CS0RCR1
/*
CS0RCR2:
APR=1(Async Page Read);
PAT=4(6 EIM clock syclks)
changed RWSC=4,OEA=0,PAT=2;
*/
writel(0x000000000, ram_reg + 0xc);//EIM_CS0RCR2
/*
CS0WCR1:
WWSC=1;
WADVA=0;WADVN=0;
WBEA=0;WBEN=0;
WEA=0;WEN=0;
WCSA=0;WCSN=0;
*/
writel(0x01000000, ram_reg + 0x10);//EIM_CS0WCR1 WWSC=3 EIM clk
/*WBCDD=0*/
writel(0x00000000, ram_reg + 0x14);
writel(0x00000000, ram_reg + 0x090);
//init pad
mxc_iomux_v3_setup_multiple_pads(mx6q_weimram_pads,ARRAY_SIZE(mx6q_weimram_pads));
//init pad
printk("imx6q weim_cs0 init\n");
}
static struct eim_mxc_pdata eim_mxc
static struct eim_mxc_pdata eim_mxc = {
.init = mx6q_setup_weim_cs,
};
static struct resource weim_fpga_resource
static struct resource weim_fpga_resource = {
.start = CS0_BASE_ADDR,
.end = CS0_BASE_ADDR + SZ_32M - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device weim_fpga_device
static struct platform_device weim_fpga_device = {
.name = "imx6q-fpga",
.id = -1,
.num_resources = 1,
.resource = &weim_fpga_resource,
.dev = {
.platform_data = &eim_mxc,
}
};
4、在board_init(void)中进行设备注册
/* 2020.8.24add eim device*/
platform_device_register(&weim_fpga_device);
5、重新编译生成内核
搞定;)
经FPGA测试,进行read、write时已能看见引脚时序逻辑,但是还不能正常读写到数据,估计是寄存器配置什么的问题,还要继续改进
后续解决方案见本人的另一篇博客
EIM总线驱动移植(二)_~~一道光的博客-CSDN博客_eim总线https://blog.csdn.net/becdecorbin/article/details/108580017
本文仅是个人的学习记录,如有偏颇还请网友不吝赐教!