os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/elphel/fpga_sdram.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : fpga_sdram333.c
00003 *! DESCRIPTION: TBD
00004 *! Copyright (C) 2002-2006 Elphel, Inc.
00005 *! -----------------------------------------------------------------------------**
00006 *!
00007 *!  This program is free software: you can redistribute it and/or modify
00008 *!  it under the terms of the GNU General Public License as published by
00009 *!  the Free Software Foundation, either version 3 of the License, or
00010 *!  (at your option) any later version.
00011 *!
00012 *!  This program is distributed in the hope that it will be useful,
00013 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 *!  GNU General Public License for more details.
00016 *!
00017 *!  You should have received a copy of the GNU General Public License
00018 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *! -----------------------------------------------------------------------------**
00020 *!  $Log: fpga_sdram353.c,v $
00021 *!  Revision 1.1.1.1  2008/11/27 20:04:00  elphel
00022 *!
00023 *!
00024 *!  Revision 1.5  2008/10/25 20:01:33  elphel
00025 *!  just put notes about not using file->f_pos in read() and write()
00026 *!
00027 *!  Revision 1.4  2008/09/22 22:55:48  elphel
00028 *!  snapshot
00029 *!
00030 *!  Revision 1.3  2008/09/16 00:49:31  elphel
00031 *!  snapshot
00032 *!
00033 *!  Revision 1.2  2008/06/16 06:51:21  elphel
00034 *!  work in progress, intermediate commit
00035 *!
00036 *!  Revision 1.1.1.1  2007/08/17 10:23:18  elphel
00037 *!  This is a fresh tree based on elphel353-2.10
00038 *!
00039 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00040 *!  switch to GPL3 license
00041 *!
00042 *!  Revision 1.6  2007/07/20 10:17:46  spectr_rain
00043 *!  *** empty log message ***
00044 *!
00045 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00046 *!  initial import into CVS
00047 *!
00048 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00049 *!  *** empty log message ***
00050 *!
00051 */
00052 /****************** INCLUDE FILES SECTION ***********************************/
00053 
00054 #include <linux/module.h>
00055 #include <linux/sched.h>
00056 #include <linux/slab.h>
00057 #include <linux/errno.h>
00058 #include <linux/kernel.h>
00059 #include <linux/fs.h>
00060 #include <linux/string.h>
00061 #include <linux/init.h>
00062 #include <linux/autoconf.h>
00063 
00064 #include <asm/system.h>
00065 //#include <asm/svinto.h>
00066 #include <asm/io.h>
00067 
00068 #include <asm/irq.h>
00069 
00070 #include <asm/delay.h>
00071 #include <asm/uaccess.h>
00072 #include <asm/elphel/c313a.h> // just for LSEEK_FSDRAM_RESET
00073 #include <asm/elphel/fpgaconfa.h>
00074 
00075 #include "fpgactrl.h"
00076 #include "fpga_sdram.h"
00077 #include "x3x3.h"
00078 
00079 #define D(x)
00080 //#define MD2(x) printk("%s:%d:",__FILE__,__LINE__);x
00081 #define MD2(x)
00082 
00083 #define DEBUG_MODE1
00084 static int sdbuf[128];
00085 static char * sdbytebuf= (char *) sdbuf;
00086 
00087 void fpga_resetSDRAM(void) {
00088     X313_SDRAM_OFF;
00089     fpga_state &= ~FPGA_STATE_SDRAM_INIT;
00090     MD2(printk("fpga_resetSDRAM()\n"));
00091 }
00092 
00093 void fpga_initSDRAM(void) {
00094 //         | 31-18 | not used 
00095 //         |    17 | RAS
00096 //         |    16 | CAS
00097 //         |    15 | WE
00098 //         | 14-13 | bank address [1:0]
00099 //         | 12-00 | address[12:0]
00100 // 0x20000 - RAS
00101 // 0x10000 - CAS
00102 // 0x08000 - WE
00103 // 0x00100 - (in mode register) - reset DLL
00104 // 0x00003 - (in mode register) - burst=8
00105 // 0x00060 - (in mode register) - CL=2.5
00106 // 0x02000 - ext mode register
00107 // 0x00001 - ext mode (OR with 0x2000) - disable DLL (0 - enable)
00108 // 0x00002 - ext mode (OR with 0x2000) - reduced drive strength (try it)
00109 
00110 
00111     X313_SDRAM_OFF;
00112     // wait 100usec
00113     udelay (100);
00114     port_csp0_addr[X313_WA_SD_MANCMD] = 0x17fff; // precharge, a[10]=1 - all banks
00115     udelay (1);
00116 //    port_csp0_addr[X313_WA_SD_MANCMD] = 0x02000; // load extended mode register - enable DLL
00117     port_csp0_addr[X313_WA_SD_MANCMD] = 0x02002; // load extended mode register - enable DLL, reduced drive strength
00118     udelay (1);
00119     port_csp0_addr[X313_WA_SD_MANCMD] = 0x00163; // load mode register - CL=2.5, burst=8 (no full fage available), reset DLL
00120     udelay (1);
00121     port_csp0_addr[X313_WA_SD_MANCMD] = 0x8000; // refresh
00122     udelay (1);
00123     port_csp0_addr[X313_WA_SD_MANCMD] = 0x8000; // refresh
00124     udelay (1);
00125     port_csp0_addr[X313_WA_SD_MANCMD] = 0x00063; // (not needed for Micron) - clear reset DLL bit in mode register
00126     udelay (1);
00127     X313_SDRAM_ON; // enable+refresh
00128     MD2(printk("fpga_initSDRAM\n"));
00129     fpga_state |= FPGA_STATE_SDRAM_INIT;
00130 }
00131 
00132 
00133 int     fsdram_ioctl(struct inode *inode, struct file *file,  unsigned int cmd, unsigned long arg) {
00134  return 0;
00135 }
00136 
00137 ssize_t fsdram_read(struct file * file, char * buf, size_t count, loff_t *off) {
00138   unsigned long p,sa,left,i,j,nb,ibp;
00139   char * bp=buf;
00140 
00141   D(printk("fsdram_read from 0x%x\n", (int) *off));
00142   if (!X313_IS_SDRAM_ON) return -EFAULT;    // SDRAM was not enabled or refresh was not on
00144   p = *off;
00145   if (p >= X313_SDRAM_SIZE)  return -EINVAL; // bigger than SDRAM
00146   if( (p + count) > X313_SDRAM_SIZE) { // truncate count 
00147     count = X313_SDRAM_SIZE - p;
00148   }
00149   left=count;
00150   if (left==0) return 0;
00151 // find start address for the sdram channel (512 bytes page aligned)
00152   sa=(p>>1) & 0x01ffff00;
00153     // program channel 3 to read maximal length
00154 #ifdef DEBUG_MODE1
00155   if (port_csp0_addr[0x2b] & 1){ X313_INIT_SDCHAN( 3, 1, 0, 0, sa , 0x3ff, 0xfff); }
00156   else                         { X313_INIT_SDCHAN( 3, 0, 0, 0, sa , 0x3ff, 0xfff); }
00157 #else
00158   X313_INIT_SDCHAN( 3, 0, 0, 0, sa , 0x3ff, 0xfff);   // 4096 rows of 32x256 16-bit words each - 64MB > than memory
00159 #endif
00160 // enable channel if it was not already
00161    X313_CHN_EN(3);
00162 //MD2(printk("0x27 <- 0x%x", (int) X313_CHN_EN_D(3)));
00163 
00164   while (left >0) {
00165 // wait SDRAM ready
00166     j=10000;
00167     while (((j--)>0) && !X313_SR(PIORDY));
00168     if (j==0) return -EFAULT;  // page not ready
00169 // read the whole page (128x32) to the buffer
00170     i=port_csp4_addr[X313_WA_SD_PIOWIN]; // will return garbage (because of latency), prepares to the next read, increments address
00171     for (i=0;i<128;i++)        sdbuf[i]=port_csp4_addr[X313_WA_SD_PIOWIN];
00172     port_csp0_addr[X313_WA_SDPIO_NEXT]=0; // advance to the next page
00173 // copy data
00174     ibp=p-(sa<<1);
00175     nb=left;
00176     if ((ibp+nb)>512) nb=512-ibp;
00177 //    D(printk ("copytouser, ibp=%x, nb=%x\n", (int) ibp, (int) nb));
00178     if (copy_to_user(bp, &sdbytebuf[ibp], nb)) return -EFAULT;
00179     left -=nb;
00180     bp+=nb;
00181     p+=nb;
00182     sa+=256;
00183   } // while (left>0)
00184   *off+=count;
00185   D(printk("count= 0x%x, pos= 0x%x\n", (int) count, (int)*off));
00186   return count;  
00187 }
00188 int read_page_to_buffer(unsigned long sa) {
00189   unsigned long i;
00190   X313_INIT_SDCHAN( 3, 0, 0, 0, sa , 0x3ff, 0xfff);   // 4096 rows of 32x256 16-bit words each
00191   // enable channel if it was not already
00192   X313_CHN_EN(3);
00193 //MD2(printk("0x27 <- 0x%x", (int) X313_CHN_EN_D(3)));
00194 // wait SDRAM ready
00195   i=10000;
00196   while (((i--)>0) && !X313_SR(PIORDY));
00197   D(printk("ready, i=%d\n",(int) i));
00198   if (i==0) return -EFAULT;
00199 // stop channel 3 from reading more data to the cache.
00200   X313_CHN_DIS(3);  // disable channel 3 access to SDRAM
00201   i=port_csp4_addr[X313_WA_SD_PIOWIN]; // will return garbage (because of latency), prepares to the next read, increments address
00202   for (i=0;i<128;i++){
00203    sdbuf[i]=port_csp4_addr[X313_WA_SD_PIOWIN];
00204   } 
00205   return 0;  
00206 }
00207 
00208 ssize_t fsdram_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00209 //  unsigned long p,sa,left,n,i,j,bi,nb,ibp;
00210   unsigned long p,sa,left,i,nb,ibp;
00211   const char * bp=buf;
00212   int fp=1; // first page
00213   D(printk("fsdram_write to 0x%x\n", (int) *off));
00214   if (!X313_IS_SDRAM_ON) return -EFAULT;    // SDRAM was not enabled or refresh was not on
00215   p = *off;
00216   if (p >= X313_SDRAM_SIZE)  return -EINVAL; // bigger than SDRAM
00217   if( (p + count) > X313_SDRAM_SIZE) { // truncate count 
00218     count = X313_SDRAM_SIZE - p;
00219   }
00220   left=count;
00221   if (left==0) return 0;
00222 // if the write starts not from the beginning of a page or is smaller than a page - read page to an internal buffer first
00223  D(printk ("p=%x, left=%x\n", (int) p, (int) left));
00224   if ((p & 0x1ff) || (left<0x200)) {
00225     sa=(p>>1) & 0x01ffff00;
00226     if (read_page_to_buffer(sa)<0) return -EFAULT;  // page not ready
00227   }
00228 // now process pages, loooking if it is a partial last (but not first, as it is already read in)
00229   while (left >0) {
00230 // find start address for the sdram channel (512 bytes page aligned)
00231     sa=(p>>1) & 0x01ffff00;
00232 // wait for write buffer empty (if not the first page)
00233     if (!fp) {
00234       i=1000;
00235       while (((i--)>0) && !X313_SR(PIOWEMPTY)) udelay(1);
00236       if (i==0) return -EFAULT;  // page not ready
00237 // is it partial (but not first) page?
00238       if ((left<0x200) && (read_page_to_buffer(sa)<0)) return -EFAULT;  // page not ready
00239     }
00240 // program channel 3 to write maximal frame size
00241     X313_INIT_SDCHAN( 3, 0, 1, 0, sa , 0x3ff, 0xfff);   // 4096 rows of 32x256 16-bit words each
00242 // enable channel if it was not already
00243     X313_CHN_EN(3);
00244     while ((left>0) && ((left>=512) || fp)) { // will be false for the last page if !fp (force to outer loop that reads buffer)
00245 // copy from user to internal buffer
00246       ibp=p-(sa<<1);
00247       nb=left;
00248       if ((ibp+nb)>512) nb=512-ibp;
00249       if (copy_from_user(&sdbytebuf[ibp], bp, nb)) return -EFAULT;
00250       bp+=nb;
00251 // wait SDRAM ready
00252       i=10000;
00253       while (((i--)>0) && !X313_SR(PIORDY));
00254       if (i==0) return -EFAULT;  // page not ready
00255 // send the whole page to SDRAM buffer
00256       for (i=0;i<128;i++)  port_csp0_addr[X313_WA_SD_PIOWIN]=sdbuf[i];
00257       port_csp0_addr[X313_WA_SDPIO_NEXT]=0; // next page - write current page to SDRAM
00258       left -=nb;
00259       p+=nb;
00260       sa+=256;
00261       fp=0;
00262     } // while ((left>0) && ((left>=256) || !fp))
00263   } // while (left >0)
00264   i=1000;
00265   while (((i--)>0) && !X313_SR(PIOWEMPTY)) udelay(1);
00266   if (i==0) return -EFAULT;  // page not ready
00267   *off+=count;
00268   D(printk("count= 0x%x, pos= 0x%x\n", (int) count, (int) *off));
00269   return count;
00270 }
00271 
00272 
00273 loff_t  fsdram_lseek(struct file * file, loff_t offset, int orig)
00274 {
00275 /*
00276  *  orig 0: position from begning
00277  *  orig 1: relative from current position
00278  *  orig 2: position from last address
00279  */
00280   D(printk("fsdram_lseek\n"));
00281   
00282   switch (orig)
00283   {
00284    case SEEK_SET:
00285      file->f_pos = offset;
00286      break;
00287    case SEEK_CUR:
00288      file->f_pos += offset;
00289      break;
00290    case SEEK_END:
00291      if (offset <=0) file->f_pos = X313_SDRAM_SIZE + offset;
00292      else {
00293        switch (offset) {
00294          case LSEEK_FSDRAM_RESET:
00295            fpga_resetSDRAM();
00296            break;
00297          default:
00298            return -EINVAL; 
00299        }
00300      }
00301      break;
00302    default:
00303      return -EINVAL;
00304   }
00305 
00306   /* truncate position */
00307   if (file->f_pos < 0) {
00308     file->f_pos = 0;    
00309     return(-EOVERFLOW);
00310   }
00311   if (file->f_pos >= X313_SDRAM_SIZE) {
00312     file->f_pos = X313_SDRAM_SIZE - 1;
00313     return(-EOVERFLOW);
00314   }
00315   return ( file->f_pos );
00316 }
00317 
00318 int     fsdram_open(struct inode *inode, struct file *filp) {
00319 // add initializing SDRAM if it was off
00320     if (!X313_IS_SDRAM_ON)  { // now will init even if only refresh was off
00321       fpga_initSDRAM();
00322       D(printk("fpga_initSDRAM\n"));
00323     }
00324 
00325  D(printk("fsdram_open\n"));
00326 
00327 inode->i_size=X313_SDRAM_SIZE;
00328   return 0;
00329 }
00330 int     fsdram_release (void){
00331  D(printk("fsdram_release\n"));
00332   return 0;
00333 }
00334 
00335 
00336 //  if (copy_from_user(&bitstream_data[buf8i],buf,count)) return -EFAULT;
00337 //     bytes_left = copy_from_user(void*to, const void *from, unsigned long n );
00338 //     bytes_left = copy_to_user(void*to, const void *from,   unsigned long n );
00339 
00340 
00341 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1