⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 virtex.c

📁 该文件是rt_linux
💻 C
字号:
/*!****************************************************************************!*! FILE NAME  : vertex.c*!*! DESCRIPTION: Implements an interface towards virtex FPGA (mounted on one of our*!              evaluation boards) from userspace using ioctl()'s*!*!              The FPGA can be programmed by copying the bit-file to /dev/fpga.*!*!                cp fpga.bit > /dev/fpga*!*!                Kernel log should look like:*!                  69900 bytes written*!                  FPGA-configuration completed, no errors*!*!              Number of bytes written depends on the FPGA*!*!                From Xilinx data sheet:*!                XCV50    559,200 bits*!                XCV100   781,216 bits*!                XCV800 4,715,616 bits*!*!              Accepted file type is the design.bit generated by Alliance*!              Design Manager.*!              This software just sends the bitfile into the device without*!              checking device type etc.*!*!              Sync-header 0xff 0xff 0xff 0xff defines the start for the*!              byte stream, everything from that position is written to the FPGA.*!*!  *! Jul 19 2002  Stefan Lundberg    Initial version.*! $Log: virtex.c,v $*! Revision 1.1  2002/06/25 09:58:58  stefanl*! New FPGA driver for Platoon*!*!*! ---------------------------------------------------------------------------*!*! (C) Copyright 2002 Axis Communications AB, LUND, SWEDEN*!*!***************************************************************************//* $Id: virtex.c,v 1.1 2002/06/25 09:58:58 stefanl Exp $ *//****************** INCLUDE FILES SECTION ***********************************/#include <linux/module.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/major.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/string.h>#include <linux/init.h>#include <linux/config.h>#include <linux/hdreg.h>#include <linux/mm.h>#include <asm/etraxvirtex.h>#include <asm/system.h>#include <asm/svinto.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/delay.h>#include "virtex.h"/******************* VIRTEX DEFINITION SECTION **************************/#define VIRTEX_DEBUG(x)#define VIRTEX_MAJOR 246  /* EXPERIMENTAL */static const char virtex_name[] = "virtex";/****************** FUNCTION DEFINITION SECTION *************************///// Read register interface for FPGA programming:////   FPGA_DONE is connected to S1CD_N G28//   FPGA_INIT_N is connected to S1IO_N G27//// Write register interface for FPGA programming:////  Bit:       15         14      13    12      9   8   7   0//        ____________________________________________________//       | fpga_write | program | cclk | reserved | cs | data |//       |____________|_________|______|__________|____|______|//// csp0 = cs_fpga1 = FPGA programming interface// csr0 = cs_fpga2 = register interface towards FPGA constructionstatic volatile short *port_csp0_word_addr;static volatile short *port_csr0_word_addr;static volatile unsigned char open_count;static volatile unsigned char bytes_written;static volatile unsigned long bytes_written_cnt;static volatile unsigned char sync_found;static volatile unsigned char sync_count;static volatile unsigned char sync_ff_count;#define WRITE_FPGA_PROG_REG(data) *port_csp0_word_addr=(data)#define SET_PROGRAM_BIT(data) (data)|(1<<14)#define SET_WRITE_BIT(data) (data)|(1<<15)#define CLR_WRITE_BIT(data) (data)&(~(1<<15))#define SET_CS_BIT(data) (data)|(1<<8)#define CLR_CS_BIT(data) (data)&(~(1<<8))#define SET_CCLK_BIT(data) (data)|(1<<13)#define CLR_CCLK_BIT(data) (data)&(~(1<<13))// Bit in read port G (always inputs)#define READ_INIT  (*R_PORT_G_DATA)&(1<<27)#define READ_DONE  (*R_PORT_G_DATA)&(1<<28)void start_virtex_program(void){  unsigned short reg_data=0;  printk("Start writing to FPGA\n");  reg_data = SET_CS_BIT(reg_data); // FPGA unselected  reg_data = SET_PROGRAM_BIT(reg_data);  WRITE_FPGA_PROG_REG(reg_data);  while(!READ_INIT); // Wait for init    reg_data = SET_WRITE_BIT(reg_data);  WRITE_FPGA_PROG_REG(reg_data);  reg_data = CLR_CS_BIT(reg_data); // FPGA selected, CS is active low  WRITE_FPGA_PROG_REG(reg_data);  return;}// According to datasheet, bytes should be reversed, it is unknown to me why.unsigned char bit_reverse(unsigned char data) {  unsigned char in=data;  unsigned short out=0;  unsigned int i=0;  for(i=0;i<8;i++) {    if(in&0x1) {      out|=0x1;    }    in=in>>1;    out=out<<1;  }  return(out>>1);  }void virtex_program(char* ptr,size_t count){  int c;  char *p;  unsigned char data;    unsigned short reg_data=0;//  short tmp_cnt;    c=count;  p=ptr;  if(!sync_found) {    c=count;    p=ptr;    while(c--) {      data=(unsigned char)*p++;      sync_count++;      if(sync_count>=256) {        printk("Sync not found, aborting\n");        return;      }      if(data==0xff) {        sync_ff_count++;      } else {        sync_ff_count=0;      }      if(sync_ff_count==4) {        sync_found=1;        VIRTEX_DEBUG(printk("Sync found at offset %d\n",sync_count));        p--;p--;p--;p--;        c++;c++;c++;c++;        break;      }    }  }  if(sync_found) {    if(bytes_written==0) {      start_virtex_program();    }    bytes_written=1;      reg_data = SET_PROGRAM_BIT(reg_data);    reg_data = SET_WRITE_BIT(reg_data);    reg_data = CLR_CS_BIT(reg_data);  //    tmp_cnt=0;        printk("*");    while(c--) {      data=(unsigned char)*p++;      data=bit_reverse(data);/* debug      tmp_cnt++;      if(tmp_cnt<=32 || c<=32 ) {        printk("0x%x ",data);       }      if(tmp_cnt==32 || c==0 ) {        printk("\n");       }*/      bytes_written_cnt++;      reg_data = CLR_CCLK_BIT(reg_data);      WRITE_FPGA_PROG_REG(reg_data|(data&0xff));      reg_data = SET_CCLK_BIT(reg_data);      WRITE_FPGA_PROG_REG(reg_data|(data&0xff));      reg_data = CLR_CCLK_BIT(reg_data);      WRITE_FPGA_PROG_REG(reg_data|(data&0xff));      }  }     return;}void stop_virtex_program(void){  unsigned short reg_data=0;  reg_data = SET_PROGRAM_BIT(reg_data);  reg_data = SET_WRITE_BIT(reg_data);  reg_data = CLR_CCLK_BIT(reg_data);  reg_data = SET_CS_BIT(reg_data); // release CS  WRITE_FPGA_PROG_REG(reg_data);  reg_data = CLR_WRITE_BIT(reg_data); // release write, important to do!  WRITE_FPGA_PROG_REG(reg_data);  printk("%d bytes written\n",bytes_written_cnt);  if(READ_DONE) {    printk("FPGA-configuration completed, no errors\n");  } else {    printk("Error, FPGA-configuration failed\n");  }  return;}static intvirtex_open(struct inode *inode, struct file *filp){  port_csp0_word_addr = port_csp0_addr;  if(open_count>=1) {    printk("FPGA Device busy, aborting\n");    return(-EBUSY);  }  open_count++;  bytes_written=0;  sync_found=0;  sync_count=0;  sync_ff_count=0;  bytes_written_cnt=0;  return(0);}static intvirtex_release(struct inode *inode, struct file *filp){  open_count--;  if(bytes_written!=0)stop_virtex_program();  return 0;}// FPGA programming interfacestatic ssize_t virtex_write(struct file * file, const char * buf,                                  size_t count, loff_t *ppos){  char *ptr;  VIRTEX_DEBUG(printk("Write FPGA count %d\n", count));    ptr=kmalloc(count, GFP_KERNEL);  if(!ptr) {    printk("FPGA device, kernel malloc failed (%d) bytes\n",count);    return -EFAULT;  }  if(copy_from_user(ptr, buf, count)) {    printk("copy_from_user failed\n");    return -EFAULT;  }    virtex_program(ptr,count);    kfree(ptr);  return count;}/* Main device API. ioctl's to write or read to/from registers. */int virtex_writereg(unsigned short theReg, unsigned short theValue){  port_csr0_word_addr[theReg]=theValue;  return(0);}unsigned short virtex_readreg(unsigned short theReg){  return(port_csr0_word_addr[theReg]);}static intvirtex_ioctl(struct inode *inode, struct file *file,	  unsigned int cmd, unsigned long arg){  if(_IOC_TYPE(cmd) != ETRAXVIRTEX_FPGA_IOCTYPE) {    return -EINVAL;  }    switch (_IOC_NR(cmd)) {    case VIRTEX_FPGA_WRITEREG:      /* write to an FPGA register */      VIRTEX_DEBUG(printk("virtex wr %d %d\n",                VIRTEX_FPGA_ARGREG(arg),               VIRTEX_FPGA_ARGVALUE(arg)));            return virtex_writereg(VIRTEX_FPGA_ARGREG(arg),                             VIRTEX_FPGA_ARGVALUE(arg));    case VIRTEX_FPGA_READREG:    {      unsigned char val;      /* read from an FPGA register */      VIRTEX_DEBUG(printk("virtex rd %d ",               VIRTEX_FPGA_ARGREG(arg)));      val = virtex_readreg(VIRTEX_FPGA_ARGREG(arg));      VIRTEX_DEBUG(printk("= %d\n", val));      return val;    }					        default:      return -EINVAL;    }return 0;}static struct file_operations virtex_fops = {	owner:    THIS_MODULE,	ioctl:    virtex_ioctl,	open:     virtex_open,        write:    virtex_write,	release:  virtex_release,};static int __initvirtex_init(void){  int res;    /* register char device */  res = register_chrdev(VIRTEX_MAJOR, virtex_name, &virtex_fops);  if(res < 0) {          printk(KERN_ERR "virtex: couldn't get a major number.\n");          return res;  }    port_csr0_word_addr = (volatile unsigned short *)                         ioremap((unsigned long)(MEM_CSR0_START |                                                MEM_NON_CACHEABLE), 16);     // see ~/platoon/rel2/platoon/os/linux/arch/cris/mm/init.c//              port_csp0_addr = (volatile unsigned long *)//                 ioremap((unsigned long)(MEM_CSP0_START |//                                         MEM_NON_CACHEABLE), 16);    open_count=0;    printk("VIRTEX(TM) FPGA driver v1.0, (c) 2002 Axis Communications AB\n");    return 0;}/* this makes sure that virtex_init is called during boot */module_init(virtex_init);/****************** END OF FILE virtex.c ********************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -