Linux驱动开发笔记:对zynq PL部分IP核的驱动开发过程_第1页
Linux驱动开发笔记:对zynq PL部分IP核的驱动开发过程_第2页
Linux驱动开发笔记:对zynq PL部分IP核的驱动开发过程_第3页
Linux驱动开发笔记:对zynq PL部分IP核的驱动开发过程_第4页
Linux驱动开发笔记:对zynq PL部分IP核的驱动开发过程_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux驱动开发笔记:对zynqPL部分IP核的驱动开发过程在对zynq进行Linux驱动开发时,除了需要针对zynq内ARM自带的控制器适配驱动外,还需要对zynqPL部分的IP核进行驱动开发。对于ARM来说,zynqPL部分的IP核就是一段地址空间,这段地址空间包含了该IP的一系列寄存器,ARM操作该IP核的寄存器也就是操作这段地址空间,而PL部分IP的驱动也就是对IP寄存器的操作。1、硬件设计在vivado内进行设计时,RapidIOIP核通过AXI总线与ARM相连,地址空间区域如图:从0x40000000-0x7FFFFFFF均为RapidIOIP的地址空间,注意这里的地址是物理地址,在zynq的裸程序中,可以通过xil_out32()或xil_in32()等函数直接操纵该地址的值,也即对RapidIOIP核寄存器的读写操作。补充一点,考虑到RapidIOIP使用的一致性以及预防配置出错,硬件设计时已经将RapidIOIP寄存器进行了正确配置,这一部分是在硬件FPGA编程时实现的,软件部分并不需要从头开始配置RapidIOIP核。因此,对RapidIOIP驱动的开发也只需要实现对寄存器的读、写这两个函数即可。2、devicetree设计

由于RapidIOIP核位于PL部分,需要在devicetree中增加相应内容,如下:

amba_pl{

#address-cells=;

#size-cells=;

compatible="simple-bus";

ranges;

srio_axi_config@40000000{

compatible="xlnx,xps-rio-1.00.a";

reg=;

};

};Amba_pl对应PL部分的amba,devicetree中原有的amba对应PS部分,两个位于同一层。3、驱动设计

RapidIOIP核驱动实现对物理地址0x40000000到0x7fffffff的读、写操作,可以参考xilinxPL部分CANIP核的驱动代码。实现过程需要注意地址的虚实转换,0x40000000开始的这一段地址是物理地址,需要将这段地址进行映射,确保CPU访问的地址经过MMU转换后确实对应这一地址。/*

*rio-xiic.c

*Copyright(c)2002-2007XilinxInc.

*Copyright(c)2009-2010IntelCorporation

*

*/

/*Supports:

*XilinxRapidIO

*/

#include#include#include#include#include#include#include#include#include#include#include#include#include#defineDRIVER_NAME"xiic-rio"#defineSRIO_ZYNQ_BASEADDR0x40000000

#defineSRIO_ZYNQ_NODE_BASEADDR0x10100

#defineSRIO_ZYNQ_MAX_HOPCOUNT13structxiic_rio{

structmutexlock;

u8*data;

};/*Weneedglobalvarriableformapedaddress*/

staticvoid__iomem*_rio_base=NULL;staticinlinevoidrio_setreg32(unsignedintaddrBase,unsignedintaddrOffset,unsignedintvalue)

{

iowrite32(value,addrBase+addrOffset);

}staticinlineintrio_getreg32(unsignedintaddrBase,unsignedintaddrOffset)

{

unsignedintreg_addr;

reg_addr=addrBase+addrOffset;

returnioread32(reg_addr);

}staticssize_thlMaintWrite(unsignedintdstId,unsignedshorthopcount,unsignedintoffset,unsignedintwritedata)

{

unsignedintreg_addr;

if(hopcount>SRIO_ZYNQ_MAX_HOPCOUNT)

{

printk("!!!error,hopcount=%d,>%d",hopcount,SRIO_ZYNQ_MAX_HOPCOUNT);

return-1;

}rio_setreg32((unsignedint)_rio_base,SRIO_ZYNQ_NODE_BASEADDR,dstId);

reg_addr=(((hopcount+1)<<24)|offset);

rio_setreg32((unsignedint)_rio_base,reg_addr,writedata);return0;

}staticssize_thlMaintRead(unsignedintdstId,unsignedshorthopcount,unsignedintoffset,void*mrdataAdr)

{

unsignedintreg_addr;

if(hopcount>SRIO_ZYNQ_MAX_HOPCOUNT)

{

printk("!!!error,hopcount=%d,>%d",hopcount,SRIO_ZYNQ_MAX_HOPCOUNT);

return-1;

}rio_setreg32((unsignedint)_rio_base,SRIO_ZYNQ_NODE_BASEADDR,dstId);

reg_addr=(((hopcount+1)<<24)|offset);mrdataAdr=rio_getreg32((unsignedint)_rio_base,reg_addr);printk("M_SRIO_MAINT_REG_READ:hopcount=%d,offset=0x%x,value=0x%x",hopcount,offset,mrdataAdr);

return0;

}staticSIMPLE_DEV_PM_OPS(xiic_rio_pm_ops,hlMaintRead,hlMaintWrite);staticintxiic_rio_probe(structplatform_device*pdev)

{

structxiic_rio*rio;

structresource*res;

unsignedintmtRdata=0;rio=kzalloc(sizeof(structxiic_rio),GFP_KERNEL);

if(!rio)

return-ENOMEM;/*GetMappedaddress*/

_rio_base=ioremap_nocache(SRIO_ZYNQ_BASEADDR,0xe000000);

if(!_rio_base)

return-ENOMEM;res=platform_get_resource(pdev,IORESOURCE_MEM,0);

platform_set_drvdata(pdev,rio);hlMaintRead(0xFF,0,0,mtRdata);

return0;

}staticintxiic_rio_remove(structplatform_device*pdev)

{

structxiic_rio*rio=platform_get_drvdata(pdev);kfree(rio);

return0;

}staticconststructof_device_idxiic_of_match[]={

{.compatible="xlnx,xps-rio-1.00.a",},

{},

};

MODULE_DEVICE_TABLE(of,xiic_of_match);staticstructplatform_driverxiic_rio_driver={

.probe=xiic_rio_probe,

.remove=xiic_rio_remove,

.driver={

.name=DRIVER_NAME,

.of_match_table=of_match_ptr(xiic_of_match),

.pm=&xiic_rio_pm_ops,

},

};module_platform_driver(xiic_rio_driver);MODULE_AUTHOR("info@");

MODULE_DESCRIPTION("XilinxRioIPCoredriver");

MODULE_LICENSE("GPLv2");上面代码中ioremap实现的就是物理地址的映射,该函数的第二个参数为映射的大小,由于模块上DDR只有1G,所以实际最大的映射空间只有224M,能访问IP核的实际地址空间为0x40000000-0x4e000000。驱动中实现读写两个函数,对zynqFPGA地址的访问可以直接调用ioread32()、iowrite32(),这两个函数和xil_out32()、xil_in32()相对应。完成驱动后修改Kconfig文件和Makefile文件,加入驱动选项,这里是合在了I2C总线驱动里面:4、测试

对该驱动的测试主要是通过调用读函数访问地址空间,判断返回值是

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论