virtex.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*!***************************************************************************
  2. *!
  3. *! FILE NAME  : vertex.c
  4. *!
  5. *! DESCRIPTION: Implements an interface towards virtex FPGA (mounted on one of our
  6. *!              evaluation boards) from userspace using ioctl()'s
  7. *!
  8. *!              The FPGA can be programmed by copying the bit-file to /dev/fpga.
  9. *!
  10. *!                cp fpga.bit > /dev/fpga
  11. *!
  12. *!                Kernel log should look like:
  13. *!                  69900 bytes written
  14. *!                  FPGA-configuration completed, no errors
  15. *!
  16. *!              Number of bytes written depends on the FPGA
  17. *!
  18. *!                From Xilinx data sheet:
  19. *!                XCV50    559,200 bits
  20. *!                XCV100   781,216 bits
  21. *!                XCV800 4,715,616 bits
  22. *!
  23. *!              Accepted file type is the design.bit generated by Alliance
  24. *!              Design Manager.
  25. *!              This software just sends the bitfile into the device without
  26. *!              checking device type etc.
  27. *!
  28. *!              Sync-header 0xff 0xff 0xff 0xff defines the start for the
  29. *!              byte stream, everything from that position is written to the FPGA.
  30. *!
  31. *!  
  32. *! Jul 19 2002  Stefan Lundberg    Initial version.
  33. *! $Log: virtex.c,v $
  34. *! Revision 1.1  2002/06/25 09:58:58  stefanl
  35. *! New FPGA driver for Platoon
  36. *!
  37. *!
  38. *! ---------------------------------------------------------------------------
  39. *!
  40. *! (C) Copyright 2002 Axis Communications AB, LUND, SWEDEN
  41. *!
  42. *!***************************************************************************/
  43. /* $Id: virtex.c,v 1.1 2002/06/25 09:58:58 stefanl Exp $ */
  44. /****************** INCLUDE FILES SECTION ***********************************/
  45. #include <linux/module.h>
  46. #include <linux/sched.h>
  47. #include <linux/slab.h>
  48. #include <linux/errno.h>
  49. #include <linux/major.h>
  50. #include <linux/kernel.h>
  51. #include <linux/fs.h>
  52. #include <linux/string.h>
  53. #include <linux/init.h>
  54. #include <linux/config.h>
  55. #include <linux/hdreg.h>
  56. #include <linux/mm.h>
  57. #include <asm/etraxvirtex.h>
  58. #include <asm/system.h>
  59. #include <asm/svinto.h>
  60. #include <asm/uaccess.h>
  61. #include <asm/io.h>
  62. #include <asm/delay.h>
  63. #include "virtex.h"
  64. /******************* VIRTEX DEFINITION SECTION **************************/
  65. #define VIRTEX_DEBUG(x)
  66. #define VIRTEX_MAJOR 246  /* EXPERIMENTAL */
  67. static const char virtex_name[] = "virtex";
  68. /****************** FUNCTION DEFINITION SECTION *************************/
  69. //
  70. // Read register interface for FPGA programming:
  71. //
  72. //   FPGA_DONE is connected to S1CD_N G28
  73. //   FPGA_INIT_N is connected to S1IO_N G27
  74. //
  75. // Write register interface for FPGA programming:
  76. //
  77. //  Bit:       15         14      13    12      9   8   7   0
  78. //        ____________________________________________________
  79. //       | fpga_write | program | cclk | reserved | cs | data |
  80. //       |____________|_________|______|__________|____|______|
  81. //
  82. // csp0 = cs_fpga1 = FPGA programming interface
  83. // csr0 = cs_fpga2 = register interface towards FPGA construction
  84. static volatile short *port_csp0_word_addr;
  85. static volatile short *port_csr0_word_addr;
  86. static volatile unsigned char open_count;
  87. static volatile unsigned char bytes_written;
  88. static volatile unsigned long bytes_written_cnt;
  89. static volatile unsigned char sync_found;
  90. static volatile unsigned char sync_count;
  91. static volatile unsigned char sync_ff_count;
  92. #define WRITE_FPGA_PROG_REG(data) *port_csp0_word_addr=(data)
  93. #define SET_PROGRAM_BIT(data) (data)|(1<<14)
  94. #define SET_WRITE_BIT(data) (data)|(1<<15)
  95. #define CLR_WRITE_BIT(data) (data)&(~(1<<15))
  96. #define SET_CS_BIT(data) (data)|(1<<8)
  97. #define CLR_CS_BIT(data) (data)&(~(1<<8))
  98. #define SET_CCLK_BIT(data) (data)|(1<<13)
  99. #define CLR_CCLK_BIT(data) (data)&(~(1<<13))
  100. // Bit in read port G (always inputs)
  101. #define READ_INIT  (*R_PORT_G_DATA)&(1<<27)
  102. #define READ_DONE  (*R_PORT_G_DATA)&(1<<28)
  103. void start_virtex_program(void)
  104. {
  105.   unsigned short reg_data=0;
  106.   printk("Start writing to FPGAn");
  107.   reg_data = SET_CS_BIT(reg_data); // FPGA unselected
  108.   reg_data = SET_PROGRAM_BIT(reg_data);
  109.   WRITE_FPGA_PROG_REG(reg_data);
  110.   while(!READ_INIT); // Wait for init
  111.   
  112.   reg_data = SET_WRITE_BIT(reg_data);
  113.   WRITE_FPGA_PROG_REG(reg_data);
  114.   reg_data = CLR_CS_BIT(reg_data); // FPGA selected, CS is active low
  115.   WRITE_FPGA_PROG_REG(reg_data);
  116.   return;
  117. }
  118. // According to datasheet, bytes should be reversed, it is unknown to me why.
  119. unsigned char bit_reverse(unsigned char data) 
  120. {
  121.   unsigned char in=data;
  122.   unsigned short out=0;
  123.   unsigned int i=0;
  124.   for(i=0;i<8;i++) {
  125.     if(in&0x1) {
  126.       out|=0x1;
  127.     }
  128.     in=in>>1;
  129.     out=out<<1;
  130.   }
  131.   return(out>>1);
  132.   
  133. }
  134. void virtex_program(char* ptr,size_t count)
  135. {
  136.   int c;
  137.   char *p;
  138.   unsigned char data;  
  139.   unsigned short reg_data=0;
  140. //  short tmp_cnt;
  141.   
  142.   c=count;
  143.   p=ptr;
  144.   if(!sync_found) {
  145.     c=count;
  146.     p=ptr;
  147.     while(c--) {
  148.       data=(unsigned char)*p++;
  149.       sync_count++;
  150.       if(sync_count>=256) {
  151.         printk("Sync not found, abortingn");
  152.         return;
  153.       }
  154.       if(data==0xff) {
  155.         sync_ff_count++;
  156.       } else {
  157.         sync_ff_count=0;
  158.       }
  159.       if(sync_ff_count==4) {
  160.         sync_found=1;
  161.         VIRTEX_DEBUG(printk("Sync found at offset %dn",sync_count));
  162.         p--;p--;p--;p--;
  163.         c++;c++;c++;c++;
  164.         break;
  165.       }
  166.     }
  167.   }
  168.   if(sync_found) {
  169.     if(bytes_written==0) {
  170.       start_virtex_program();
  171.     }
  172.     bytes_written=1;
  173.   
  174.     reg_data = SET_PROGRAM_BIT(reg_data);
  175.     reg_data = SET_WRITE_BIT(reg_data);
  176.     reg_data = CLR_CS_BIT(reg_data);
  177.   
  178. //    tmp_cnt=0;
  179.     
  180.     printk("*");
  181.     while(c--) {
  182.       data=(unsigned char)*p++;
  183.       data=bit_reverse(data);
  184. /* debug
  185.       tmp_cnt++;
  186.       if(tmp_cnt<=32 || c<=32 ) {
  187.         printk("0x%x ",data); 
  188.       }
  189.       if(tmp_cnt==32 || c==0 ) {
  190.         printk("n"); 
  191.       }
  192. */
  193.       bytes_written_cnt++;
  194.       reg_data = CLR_CCLK_BIT(reg_data);
  195.       WRITE_FPGA_PROG_REG(reg_data|(data&0xff));
  196.       reg_data = SET_CCLK_BIT(reg_data);
  197.       WRITE_FPGA_PROG_REG(reg_data|(data&0xff));
  198.       reg_data = CLR_CCLK_BIT(reg_data);
  199.       WRITE_FPGA_PROG_REG(reg_data|(data&0xff));
  200.   
  201.     }
  202.   }
  203.    
  204.   return;
  205. }
  206. void stop_virtex_program(void)
  207. {
  208.   unsigned short reg_data=0;
  209.   reg_data = SET_PROGRAM_BIT(reg_data);
  210.   reg_data = SET_WRITE_BIT(reg_data);
  211.   reg_data = CLR_CCLK_BIT(reg_data);
  212.   reg_data = SET_CS_BIT(reg_data); // release CS
  213.   WRITE_FPGA_PROG_REG(reg_data);
  214.   reg_data = CLR_WRITE_BIT(reg_data); // release write, important to do!
  215.   WRITE_FPGA_PROG_REG(reg_data);
  216.   printk("%d bytes writtenn",bytes_written_cnt);
  217.   if(READ_DONE) {
  218.     printk("FPGA-configuration completed, no errorsn");
  219.   } else {
  220.     printk("Error, FPGA-configuration failedn");
  221.   }
  222.   return;
  223. }
  224. static int
  225. virtex_open(struct inode *inode, struct file *filp)
  226. {
  227.   port_csp0_word_addr = port_csp0_addr;
  228.   if(open_count>=1) {
  229.     printk("FPGA Device busy, abortingn");
  230.     return(-EBUSY);
  231.   }
  232.   open_count++;
  233.   bytes_written=0;
  234.   sync_found=0;
  235.   sync_count=0;
  236.   sync_ff_count=0;
  237.   bytes_written_cnt=0;
  238.   return(0);
  239. }
  240. static int
  241. virtex_release(struct inode *inode, struct file *filp)
  242. {
  243.   open_count--;
  244.   if(bytes_written!=0)stop_virtex_program();
  245.   return 0;
  246. }
  247. // FPGA programming interface
  248. static ssize_t virtex_write(struct file * file, const char * buf, 
  249.                                  size_t count, loff_t *ppos)
  250. {
  251.   char *ptr;
  252.   VIRTEX_DEBUG(printk("Write FPGA count %dn", count));
  253.   
  254.   ptr=kmalloc(count, GFP_KERNEL);
  255.   if(!ptr) {
  256.     printk("FPGA device, kernel malloc failed (%d) bytesn",count);
  257.     return -EFAULT;
  258.   }
  259.   if(copy_from_user(ptr, buf, count)) {
  260.     printk("copy_from_user failedn");
  261.     return -EFAULT;
  262.   }
  263.   
  264.   virtex_program(ptr,count);
  265.   
  266.   kfree(ptr);
  267.   return count;
  268. }
  269. /* Main device API. ioctl's to write or read to/from registers.
  270.  */
  271. int virtex_writereg(unsigned short theReg, unsigned short theValue)
  272. {
  273.   port_csr0_word_addr[theReg]=theValue;
  274.   return(0);
  275. }
  276. unsigned short virtex_readreg(unsigned short theReg)
  277. {
  278.   return(port_csr0_word_addr[theReg]);
  279. }
  280. static int
  281. virtex_ioctl(struct inode *inode, struct file *file,
  282.   unsigned int cmd, unsigned long arg)
  283. {
  284.   if(_IOC_TYPE(cmd) != ETRAXVIRTEX_FPGA_IOCTYPE) {
  285.     return -EINVAL;
  286.   }
  287.   
  288.   switch (_IOC_NR(cmd)) {
  289.     case VIRTEX_FPGA_WRITEREG:
  290.       /* write to an FPGA register */
  291.       VIRTEX_DEBUG(printk("virtex wr %d %dn", 
  292.                VIRTEX_FPGA_ARGREG(arg),
  293.                VIRTEX_FPGA_ARGVALUE(arg)));
  294.       
  295.       return virtex_writereg(VIRTEX_FPGA_ARGREG(arg),
  296.                              VIRTEX_FPGA_ARGVALUE(arg));
  297.     case VIRTEX_FPGA_READREG:
  298.     {
  299.       unsigned char val;
  300.       /* read from an FPGA register */
  301.       VIRTEX_DEBUG(printk("virtex rd %d ", 
  302.               VIRTEX_FPGA_ARGREG(arg)));
  303.       val = virtex_readreg(VIRTEX_FPGA_ARGREG(arg));
  304.       VIRTEX_DEBUG(printk("= %dn", val));
  305.       return val;
  306.     }     
  307.     default:
  308.       return -EINVAL;
  309.     }
  310. return 0;
  311. }
  312. static struct file_operations virtex_fops = {
  313. owner:    THIS_MODULE,
  314. ioctl:    virtex_ioctl,
  315. open:     virtex_open,
  316.         write:    virtex_write,
  317. release:  virtex_release,
  318. };
  319. static int __init
  320. virtex_init(void)
  321. {
  322.   int res;
  323.   
  324.   /* register char device */
  325.   res = register_chrdev(VIRTEX_MAJOR, virtex_name, &virtex_fops);
  326.   if(res < 0) {
  327.           printk(KERN_ERR "virtex: couldn't get a major number.n");
  328.           return res;
  329.   }
  330.   
  331.   port_csr0_word_addr = (volatile unsigned short *) 
  332.                         ioremap((unsigned long)(MEM_CSR0_START |
  333.                                                 MEM_NON_CACHEABLE), 16);
  334.      
  335. // see ~/platoon/rel2/platoon/os/linux/arch/cris/mm/init.c
  336. //              port_csp0_addr = (volatile unsigned long *)
  337. //                 ioremap((unsigned long)(MEM_CSP0_START |
  338. //                                         MEM_NON_CACHEABLE), 16);
  339.   
  340.   open_count=0;
  341.   
  342.   printk("VIRTEX(TM) FPGA driver v1.0, (c) 2002 Axis Communications ABn");
  343.   
  344.   return 0;
  345. }
  346. /* this makes sure that virtex_init is called during boot */
  347. module_init(virtex_init);
  348. /****************** END OF FILE virtex.c ********************************/