os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/elphel/fpga_sdram353.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  2007/08/17 10:23:18  elphel
00022 *!  This is a fresh tree based on elphel353-2.10
00023 *!
00024 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00025 *!  switch to GPL3 license
00026 *!
00027 *!  Revision 1.6  2007/07/20 10:17:46  spectr_rain
00028 *!  *** empty log message ***
00029 *!
00030 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00031 *!  initial import into CVS
00032 *!
00033 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00034 *!  *** empty log message ***
00035 *!
00036 */
00037 /****************** INCLUDE FILES SECTION ***********************************/
00038 
00039 #include <linux/module.h>
00040 #include <linux/sched.h>
00041 #include <linux/slab.h>
00042 #include <linux/errno.h>
00043 #include <linux/kernel.h>
00044 #include <linux/fs.h>
00045 #include <linux/string.h>
00046 #include <linux/init.h>
00047 #include <linux/autoconf.h>
00048 
00049 #include <asm/system.h>
00050 //#include <asm/svinto.h>
00051 #include <asm/io.h>
00052 
00053 #include <asm/irq.h>
00054 
00055 #include <asm/delay.h>
00056 #include <asm/uaccess.h>
00057 #include <asm/elphel/fpgactrl.h>
00058 
00059 #include "fpgactrl.h"
00060 #include "fpga_sdram.h"
00061 #include "x3x3.h"
00062 
00063 #define D(x)
00064 #define DEBUG_MODE1
00065 static int sdbuf[128];
00066 static char * sdbytebuf= (char *) sdbuf;
00067 
00068 
00069 void fpga_initSDRAM(void) {
00070 #if 0 // forced init - checks outside
00071 // is SDRAM already initialized?
00072     if (X313_IS_SDRAM_ON) {
00073       D(printk ("SDRAM already initialized\n"));
00074       return;
00075     }
00076 #endif
00077 //         | 31-18 | not used 
00078 //         |    17 | RAS
00079 //         |    16 | CAS
00080 //         |    15 | WE
00081 //         | 14-13 | bank address [1:0]
00082 //         | 12-00 | address[12:0]
00083 // 0x20000 - RAS
00084 // 0x10000 - CAS
00085 // 0x08000 - WE
00086 // 0x00100 - (in mode register) - reset DLL
00087 // 0x00003 - (in mode register) - burst=8
00088 // 0x00060 - (in mode register) - CL=2.5
00089 // 0x02000 - ext mode register
00090 // 0x00001 - ext mode (OR with 0x2000) - disable DLL (0 - enable)
00091 // 0x00002 - ext mode (OR with 0x2000) - reduced drive strength (try it)
00092 
00093 
00094     X313_SDRAM_OFF;
00095     // wait 100usec
00096     udelay (100);
00097     port_csp0_addr[X313_WA_SD_MANCMD] = 0x17fff; // precharge, a[10]=1 - all banks
00098     udelay (1);
00099 //    port_csp0_addr[X313_WA_SD_MANCMD] = 0x02000; // load extended mode register - enable DLL
00100     port_csp0_addr[X313_WA_SD_MANCMD] = 0x02002; // load extended mode register - enable DLL, reduced drive strength
00101     udelay (1);
00102     port_csp0_addr[X313_WA_SD_MANCMD] = 0x00163; // load mode register - CL=2.5, burst=8 (no full fage available), reset DLL
00103     udelay (1);
00104     port_csp0_addr[X313_WA_SD_MANCMD] = 0x8000; // refresh
00105     udelay (1);
00106     port_csp0_addr[X313_WA_SD_MANCMD] = 0x8000; // refresh
00107     udelay (1);
00108     port_csp0_addr[X313_WA_SD_MANCMD] = 0x00063; // (not needed for Micron) - clear reset DLL bit in mode register
00109     udelay (1);
00110     X313_SDRAM_ON; // enable+refresh
00111     D(printk("fpga_initSDRAM\n"));
00112 }
00113 
00114 
00115 int     fsdram_ioctl(struct inode *inode, struct file *file,  unsigned int cmd, unsigned long arg) {
00116  return 0;
00117 }
00118 
00119 ssize_t fsdram_read(struct file * file, char * buf, size_t count, loff_t *off) {
00120   unsigned long p,sa,left,i,j,nb,ibp;
00121   char * bp=buf;
00122 
00123   D(printk("fsdram_read from 0x%x\n", (int) *off));
00124   if (!X313_IS_SDRAM_ON) return -EFAULT;    // SDRAM was not enabled or refresh was not on
00125 //  p = file->f_pos;
00126   p = *off;
00127   if (p >= X313_SDRAM_SIZE)  return -EINVAL; // bigger than SDRAM
00128   if( (p + count) > X313_SDRAM_SIZE) { // truncate count 
00129     count = X313_SDRAM_SIZE - p;
00130   }
00131   left=count;
00132   if (left==0) return 0;
00133 // find start address for the sdram channel (512 bytes page aligned)
00134   sa=(p>>1) & 0x01ffff00;
00135     // program channel 3 to read maximal length
00136 #ifdef DEBUG_MODE1
00137   if (port_csp0_addr[0x2b] & 1){ X313_INIT_SDCHAN( 3, 1, 0, 0, sa , 0x3ff, 0xfff); }
00138   else                         { X313_INIT_SDCHAN( 3, 0, 0, 0, sa , 0x3ff, 0xfff); }
00139 #else
00140   X313_INIT_SDCHAN( 3, 0, 0, 0, sa , 0x3ff, 0xfff);   // 4096 rows of 32x256 16-bit words each - 64MB > than memory
00141 #endif
00142 // enable channel if it was not already
00143    X313_CHN_EN(3);
00144   while (left >0) {
00145 // wait SDRAM ready
00146     j=10000;
00147     while (((j--)>0) && !X313_SR(PIORDY));
00148     if (j==0) return -EFAULT;  // page not ready
00149 // read the whole page (128x32) to the buffer
00150     i=port_csp4_addr[X313_WA_SD_PIOWIN]; // will return garbage (because of latency), prepares to the next read, increments address
00151     for (i=0;i<128;i++)        sdbuf[i]=port_csp4_addr[X313_WA_SD_PIOWIN];
00152     port_csp0_addr[X313_WA_SDPIO_NEXT]=0; // advance to the next page
00153 // copy data
00154     ibp=p-(sa<<1);
00155     nb=left;
00156     if ((ibp+nb)>512) nb=512-ibp;
00157 //    D(printk ("copytouser, ibp=%x, nb=%x\n", (int) ibp, (int) nb));
00158     if (copy_to_user(bp, &sdbytebuf[ibp], nb)) return -EFAULT;
00159     left -=nb;
00160     bp+=nb;
00161     p+=nb;
00162     sa+=256;
00163   } // while (left>0)
00164 //  file->f_pos+=count;
00165   *off+=count;
00166   D(printk("count= 0x%x, pos= 0x%x\n", (int) count, (int)*off));
00167   return count;  
00168 }
00169 int read_page_to_buffer(unsigned long sa) {
00170   unsigned long i;
00171   X313_INIT_SDCHAN( 3, 0, 0, 0, sa , 0x3ff, 0xfff);   // 4096 rows of 32x256 16-bit words each
00172   // enable channel if it was not already
00173   X313_CHN_EN(3);
00174 // wait SDRAM ready
00175   i=10000;
00176   while (((i--)>0) && !X313_SR(PIORDY));
00177   D(printk("ready, i=%d\n",(int) i));
00178   if (i==0) return -EFAULT;
00179 // stop channel 3 from reading more data to the cache.
00180   X313_CHN_DIS(3);  // disable channel 3 access to SDRAM
00181   i=port_csp4_addr[X313_WA_SD_PIOWIN]; // will return garbage (because of latency), prepares to the next read, increments address
00182   for (i=0;i<128;i++){
00183    sdbuf[i]=port_csp4_addr[X313_WA_SD_PIOWIN];
00184   } 
00185   return 0;  
00186 }
00187 
00188 ssize_t fsdram_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00189 //  unsigned long p,sa,left,n,i,j,bi,nb,ibp;
00190   unsigned long p,sa,left,i,nb,ibp;
00191   const char * bp=buf;
00192   int fp=1; // first page
00193   D(printk("fsdram_write to 0x%x\n", (int) *off));
00194   if (!X313_IS_SDRAM_ON) return -EFAULT;    // SDRAM was not enabled or refresh was not on
00195 //  p = file->f_pos;
00196   p = *off;
00197   if (p >= X313_SDRAM_SIZE)  return -EINVAL; // bigger than SDRAM
00198   if( (p + count) > X313_SDRAM_SIZE) { // truncate count 
00199     count = X313_SDRAM_SIZE - p;
00200   }
00201   left=count;
00202   if (left==0) return 0;
00203 // if the write starts not from the beginning of a page or is smaller than a page - read page to an internal buffer first
00204  D(printk ("p=%x, left=%x\n", (int) p, (int) left));
00205   if ((p & 0x1ff) || (left<0x200)) {
00206     sa=(p>>1) & 0x01ffff00;
00207     if (read_page_to_buffer(sa)<0) return -EFAULT;  // page not ready
00208   }
00209 // now process pages, loooking if it is a partial last (but not first, as it is already read in)
00210   while (left >0) {
00211 // find start address for the sdram channel (512 bytes page aligned)
00212     sa=(p>>1) & 0x01ffff00;
00213 // wait for write buffer empty (if not the first page)
00214     if (!fp) {
00215       i=1000;
00216       while (((i--)>0) && !X313_SR(PIOWEMPTY)) udelay(1);
00217       if (i==0) return -EFAULT;  // page not ready
00218 // is it partial (but not first) page?
00219       if ((left<0x200) && (read_page_to_buffer(sa)<0)) return -EFAULT;  // page not ready
00220     }
00221 // program channel 3 to write maximal frame size
00222     X313_INIT_SDCHAN( 3, 0, 1, 0, sa , 0x3ff, 0xfff);   // 4096 rows of 32x256 16-bit words each
00223 // enable channel if it was not already
00224     X313_CHN_EN(3);
00225     while ((left>0) && ((left>=512) || fp)) { // will be false for the last page if !fp (force to outer loop that reads buffer)
00226 // copy from user to internal buffer
00227       ibp=p-(sa<<1);
00228       nb=left;
00229       if ((ibp+nb)>512) nb=512-ibp;
00230       if (copy_from_user(&sdbytebuf[ibp], bp, nb)) return -EFAULT;
00231       bp+=nb;
00232 // wait SDRAM ready
00233       i=10000;
00234       while (((i--)>0) && !X313_SR(PIORDY));
00235       if (i==0) return -EFAULT;  // page not ready
00236 // send the whole page to SDRAM buffer
00237       for (i=0;i<128;i++)  port_csp0_addr[X313_WA_SD_PIOWIN]=sdbuf[i];
00238       port_csp0_addr[X313_WA_SDPIO_NEXT]=0; // next page - write current page to SDRAM
00239       left -=nb;
00240       p+=nb;
00241       sa+=256;
00242       fp=0;
00243     } // while ((left>0) && ((left>=256) || !fp))
00244   } // while (left >0)
00245   i=1000;
00246   while (((i--)>0) && !X313_SR(PIOWEMPTY)) udelay(1);
00247   if (i==0) return -EFAULT;  // page not ready
00248 //  file->f_pos+=count;
00249   *off+=count;
00250   D(printk("count= 0x%x, pos= 0x%x\n", (int) count, (int) *off));
00251   return count;
00252 }
00253 
00254 
00255 loff_t  fsdram_lseek(struct file * file, loff_t offset, int orig)
00256 {
00257 /*
00258  *  orig 0: position from begning
00259  *  orig 1: relative from current position
00260  *  orig 2: position from last address
00261  */
00262   D(printk("fsdram_lseek\n"));
00263   
00264   switch (orig)
00265   {
00266    case 0:
00267      file->f_pos = offset;
00268      break;
00269    case 1:
00270      file->f_pos += offset;
00271      break;
00272    case 2:
00273      file->f_pos = X313_SDRAM_SIZE + offset;
00274      break;
00275    default:
00276      return -EINVAL;
00277   }
00278 
00279   /* truncate position */
00280   if (file->f_pos < 0) {
00281     file->f_pos = 0;    
00282     return(-EOVERFLOW);
00283   }
00284   
00285   if (file->f_pos >= X313_SDRAM_SIZE) {
00286     file->f_pos = X313_SDRAM_SIZE - 1;
00287     return(-EOVERFLOW);
00288   }
00289   return ( file->f_pos );
00290 }
00291 
00292 int     fsdram_open(struct inode *inode, struct file *filp) {
00293 // add initializing SDRAM if it was off
00294     if (!X313_IS_SDRAM_ON)  { // now will init even if only refresh was off
00295       fpga_initSDRAM();
00296       D(printk("fpga_initSDRAM\n"));
00297     }
00298 
00299  D(printk("fsdram_open\n"));
00300 
00301 inode->i_size=X313_SDRAM_SIZE;
00302   return 0;
00303 }
00304 int     fsdram_release (void){
00305  D(printk("fsdram_release\n"));
00306   return 0;
00307 }
00308 
00309 
00310 //  if (copy_from_user(&bitstream_data[buf8i],buf,count)) return -EFAULT;
00311 //     bytes_left = copy_from_user(void*to, const void *from, unsigned long n );
00312 //     bytes_left = copy_to_user(void*to, const void *from,   unsigned long n );
00313 
00314 
00315 

Generated on Thu Aug 7 16:19:00 2008 for elphel by  doxygen 1.5.1