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

📄 eeprom.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
   case 0:     file->f_pos = offset;     break;   case 1:     file->f_pos += offset;     break;   case 2:     file->f_pos = eeprom.size - offset;     break;   default:     return -EINVAL;  }  /* truncate position */  if (file->f_pos < 0)  {    file->f_pos = 0;        return(-EOVERFLOW);  }    if (file->f_pos >= eeprom.size)  {    file->f_pos = eeprom.size - 1;    return(-EOVERFLOW);  }  return ( file->f_pos );}/* Reads data from eeprom. */static int eeprom_read_buf(loff_t addr, char * buf, int count){  struct file f;  f.f_pos = addr;  return eeprom_read(&f, buf, count, &addr);}/* Reads data from eeprom. */static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t *off){  int read=0;  unsigned long p = file->f_pos;  unsigned char page;  if(p >= eeprom.size)  /* Address i 0 - (size-1) */  {    return -EFAULT;  }    while(eeprom.busy)  {    interruptible_sleep_on(&eeprom.wait_q);    /* bail out if we get interrupted */    if (signal_pending(current))      return -EINTR;      }  eeprom.busy++;  page = (unsigned char) (p >> 8);    if(!eeprom_address(p))  {    printk(KERN_INFO "%s: Read failed to address the eeprom: "           "0x%08X (%i) page: %i\n", eeprom_name, (int)p, (int)p, page);    i2c_stop();        /* don't forget to wake them up */    eeprom.busy--;    wake_up_interruptible(&eeprom.wait_q);      return -EFAULT;  }  if( (p + count) > eeprom.size)  {    /* truncate count */    count = eeprom.size - p;  }  /* stop dummy write op and initiate the read op */  i2c_start();  /* special case for small eeproms */  if(eeprom.size < EEPROM_16KB)  {    i2c_outbyte( eeprom.select_cmd | 1 | (page << 1) );  }  /* go on with the actual read */  read = read_from_eeprom( buf, count);    if(read > 0)  {    file->f_pos += read;  }  eeprom.busy--;  wake_up_interruptible(&eeprom.wait_q);  return read;}/* Writes data to eeprom. */static int eeprom_write_buf(loff_t addr, const char * buf, int count){  struct file f;  f.f_pos = addr;    return eeprom_write(&f, buf, count, &addr);}/* Writes data to eeprom. */static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,                            loff_t *off){  int i, written, restart=1;  unsigned long p;  if (verify_area(VERIFY_READ, buf, count))  {    return -EFAULT;  }  while(eeprom.busy)  {    interruptible_sleep_on(&eeprom.wait_q);    /* bail out if we get interrupted */    if (signal_pending(current))      return -EINTR;  }  eeprom.busy++;  for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++)  {    restart = 0;    written = 0;    p = file->f_pos;           while( (written < count) && (p < eeprom.size))    {      /* address the eeprom */      if(!eeprom_address(p))      {        printk(KERN_INFO "%s: Write failed to address the eeprom: "               "0x%08X (%i) \n", eeprom_name, (int)p, (int)p);        i2c_stop();                /* don't forget to wake them up */        eeprom.busy--;        wake_up_interruptible(&eeprom.wait_q);        return -EFAULT;      }#ifdef EEPROM_ADAPTIVE_TIMING            /* Adaptive algorithm to adjust timing */      if (eeprom.retry_cnt_addr > 0)      {        /* To Low now */        D(printk(">D=%i d=%i\n",               eeprom.usec_delay_writecycles, eeprom.usec_delay_step));        if (eeprom.usec_delay_step < 4)        {          eeprom.usec_delay_step++;          eeprom.usec_delay_writecycles += eeprom.usec_delay_step;        }        else        {          if (eeprom.adapt_state > 0)          {            /* To Low before */            eeprom.usec_delay_step *= 2;            if (eeprom.usec_delay_step > 2)            {              eeprom.usec_delay_step--;            }            eeprom.usec_delay_writecycles += eeprom.usec_delay_step;          }          else if (eeprom.adapt_state < 0)          {            /* To High before (toggle dir) */            eeprom.usec_delay_writecycles += eeprom.usec_delay_step;            if (eeprom.usec_delay_step > 1)            {              eeprom.usec_delay_step /= 2;              eeprom.usec_delay_step--;            }          }        }        eeprom.adapt_state = 1;      }      else      {        /* To High (or good) now */        D(printk("<D=%i d=%i\n",               eeprom.usec_delay_writecycles, eeprom.usec_delay_step));                if (eeprom.adapt_state < 0)        {          /* To High before */          if (eeprom.usec_delay_step > 1)          {            eeprom.usec_delay_step *= 2;            eeprom.usec_delay_step--;                        if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step)            {              eeprom.usec_delay_writecycles -= eeprom.usec_delay_step;            }          }        }        else if (eeprom.adapt_state > 0)        {          /* To Low before (toggle dir) */          if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step)          {            eeprom.usec_delay_writecycles -= eeprom.usec_delay_step;          }          if (eeprom.usec_delay_step > 1)          {            eeprom.usec_delay_step /= 2;            eeprom.usec_delay_step--;          }                    eeprom.adapt_state = -1;        }        if (eeprom.adapt_state > -100)        {          eeprom.adapt_state--;        }        else        {          /* Restart adaption */          D(printk("#Restart\n"));          eeprom.usec_delay_step++;        }      }#endif /* EEPROM_ADAPTIVE_TIMING */      /* write until we hit a page boundary or count */      do      {        i2c_outbyte(buf[written]);                if(!i2c_getack())        {          restart=1;          printk(KERN_INFO "%s: write error, retrying. %d\n", eeprom_name, i);          i2c_stop();          break;        }        written++;        p++;              } while( written < count && ( p % eeprom.sequential_write_pagesize ));      /* end write cycle */      i2c_stop();      i2c_delay(eeprom.usec_delay_writecycles);    } /* while */  } /* for  */  eeprom.busy--;  wake_up_interruptible(&eeprom.wait_q);  if (written == 0 && file->f_pos >= eeprom.size){    return -ENOSPC;  }  file->f_pos += written;  return written;}/* Closes the device. */static int eeprom_close(struct inode * inode, struct file * file){  /* do nothing for now */  return 0;}/* Sets the current address of the eeprom. */static int eeprom_address(unsigned long addr){  int i;  unsigned char page, offset;  page   = (unsigned char) (addr >> 8);  offset = (unsigned char)  addr;  for(i = 0; i < EEPROM_RETRIES; i++)  {    /* start a dummy write for addressing */    i2c_start();    if(eeprom.size == EEPROM_16KB)    {      i2c_outbyte( eeprom.select_cmd );       i2c_getack();      i2c_outbyte(page);     }    else    {      i2c_outbyte( eeprom.select_cmd | (page << 1) );     }    if(!i2c_getack())    {      /* retry */      i2c_stop();      /* Must have a delay here.. 500 works, >50, 100->works 5th time*/      i2c_delay(MAX_WRITEDELAY_US / EEPROM_RETRIES * i);      /* The chip needs up to 10 ms from write stop to next start */         }    else    {      i2c_outbyte(offset);            if(!i2c_getack())      {        /* retry */        i2c_stop();      }      else        break;    }  }        eeprom.retry_cnt_addr = i;  D(printk("%i\n", eeprom.retry_cnt_addr));  if(eeprom.retry_cnt_addr == EEPROM_RETRIES)  {    /* failed */    return 0;  }  return 1;}/* Reads from current address. */static int read_from_eeprom(char * buf, int count){  int i, read=0;  for(i = 0; i < EEPROM_RETRIES; i++)  {        if(eeprom.size == EEPROM_16KB)    {      i2c_outbyte( eeprom.select_cmd | 1 );    }    if(i2c_getack())    {      break;    }  }    if(i == EEPROM_RETRIES)  {    printk(KERN_INFO "%s: failed to read from eeprom\n", eeprom_name);    i2c_stop();        return -EFAULT;  }  while( (read < count))  {        if (put_user(i2c_inbyte(), &buf[read++]))    {      i2c_stop();      return -EFAULT;    }    /*     *  make sure we don't ack last byte or you will get very strange     *  results!     */    if(read < count)    {      i2c_sendack();    }  }  /* stop the operation */  i2c_stop();  return read;}/* Disables write protection if applicable. */#define DBP_SAVE(x)#define ax_printf printkstatic void eeprom_disable_write_protect(void){  /* Disable write protect */  if (eeprom.size == EEPROM_8KB)  {    /* Step 1 Set WEL = 1 (write 00000010 to address 1FFFh */    i2c_start();    i2c_outbyte(0xbe);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false\n"));    }    i2c_outbyte(0xFF);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 2\n"));    }    i2c_outbyte(0x02);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 3\n"));    }    i2c_stop();    i2c_delay(1000);    /* Step 2 Set RWEL = 1 (write 00000110 to address 1FFFh */    i2c_start();    i2c_outbyte(0xbe);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 55\n"));    }    i2c_outbyte(0xFF);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 52\n"));    }    i2c_outbyte(0x06);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 53\n"));    }    i2c_stop();        /* Step 3 Set BP1, BP0, and/or WPEN bits (write 00000110 to address 1FFFh */    i2c_start();    i2c_outbyte(0xbe);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 56\n"));    }    i2c_outbyte(0xFF);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 57\n"));    }    i2c_outbyte(0x06);    if(!i2c_getack())    {      DBP_SAVE(ax_printf("Get ack returns false 58\n"));    }    i2c_stop();        /* Write protect disabled */  }}module_init(eeprom_init);

⌨️ 快捷键说明

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