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

📄 eeprom.c

📁 IBM source for pallas/vulcan/vesta
💻 C
字号:
/*----------------------------------------------------------------------------+|       This source code has been made available to you by IBM on an AS-IS|       basis.  Anyone receiving this source is licensed under IBM|       copyrights to use it in any way he or she deems fit, including|       copying it, modifying it, compiling it, and redistributing it either|       with or without modifications.  No license under IBM patents or|       patent applications is to be implied by the copyright license.||       Any user of this software should understand that IBM cannot provide|       technical support for this software and will not be responsible for|       any consequences resulting from the use of this software.||       Any person who transfers this source code or any derivative work|       must include the IBM copyright notice, this paragraph, and the|       preceding two paragraphs in the transferred software.||       COPYRIGHT   I B M   CORPORATION 1997|       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Author:    Neil Leeder| Component: EEPROM driver| File:      eeprom.c| Purpose:   Implement EEPROM device driver functions.| Changes:| Date:      Author  Comment:| ---------  ------  --------| 29-Aug-97  NL      Created| 18-Nov-97  MPT     Added semaphores, and debug options| 17-Feb-99  MPT     Port to Romeo| 24-Jun-99  MPT     Major rewrite to handle all cases correctly| 28-Jun-00  TJC     Port to STB0210x.| 04-Jun-01	 SL		 Port to Linux on Redwood4 and add write protection operation| 12-Jul-02	 YYD	 Add support of RW6 (x24256)+----------------------------------------------------------------------------*//*-----------------------------------------------------------------------------| Note: This is not a eeprom driver, instead it is a eeprom utility library which| operates eeprom by I2C device driver.+------------------------------------------------------------------------------*/#include <stdio.h>#include <sys/wait.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>#include "eeprom.h"#ifdef  DEBUG#define PRINTF(fmt,args...)			printf(fmt,##args)#else#define PRINTF(fmt,args...)#endifstatic int eeprom_i2c_address = EEPROM_I2C_ADDRESS_WRITE;#if defined(__DRV_FOR_PALLAS__) || defined(__DRV_FOR_VESTA__)/*----------------------------------------------------------------------------+| Function prototypes.+----------------------------------------------------------------------------*/static int do_write_i2c(int fd, int hi_adr, int lo_adr,                        char *data, int length);static int i2c_page_write(int fd, int hi_adr, int lo_adr,                          char *data, int length);/*----------------------------------------------------------------------------+| Eeprom_init.+----------------------------------------------------------------------------*/int eeprom_write_begin(int fd){    unsigned char wrbuf;    wrbuf = EEPROM_WPR_WEL;    /* Redwood5 boards were initially configured with the eeprom i2c address */    /* at 0xC0. Later versions of the board were configured with the eeprom  */    /* i2c address at 0x40. The following code determines which i2c address  */    /* by first writing to the eeprom at address 0xC0. If that fails it tries*/    /* 0x40.                                                                 */    eeprom_i2c_address = EEPROM_I2C_ADDRESS_WRITE;    if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)    {        eeprom_i2c_address = (0x40)>>1;        if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)	{	  printf("do_write_i2c failure\n");          return -1;	}    }    printf("eeprom address = 0x%X\n",eeprom_i2c_address<<1);    wrbuf = EEPROM_WPR_WEL | EEPROM_WPR_RWEL;    if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)        return -1;    wrbuf = EEPROM_WPR_WEL;        if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)        return -1;        usleep(10);        return 0;}int eeprom_write_end(int fd){    char wrbuf;        wrbuf = EEPROM_WPR_WEL;        if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)        return -1;        wrbuf = EEPROM_WPR_WEL | EEPROM_WPR_RWEL;        if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)        return -1;        wrbuf = EEPROM_WPR_WEL | EEPROM_WPR_WPEN;        if (do_write_i2c(fd, EEPROM_PROT_HI, 0xff, &wrbuf, 1) < 0)        return -1;        usleep(10);        return 0;}static int i2c_page_write(int fd, int hi_adr, int lo_adr,                          char *data, int length){    int left, len, off, rem;        off = 0;    left = length;    PRINTF("EEPROM: Page write hi = %d, lo = %d, len= %d\n",        hi_adr, lo_adr, length);        if (left > EEPROM_PAGE_LEN)        len = EEPROM_PAGE_LEN;    else        len = left;            /*if ((rem = (lo_adr % EEPROM_PAGE_LEN)) != 0)        {        len = len - rem;}*/        //fit write data in one page    if(( rem = (EEPROM_PAGE_LEN - (lo_adr % EEPROM_PAGE_LEN))) != 0 )    {        if( len > rem )            len = rem;    }        if (do_write_i2c(fd, hi_adr, lo_adr + off, data + off, len) < 0)    {        PRINTF("EEPROM: page write error\n");        return -1;    }        usleep(10);    left -= len;    off += len;        while (left)    {        if (left > EEPROM_PAGE_LEN)            len = EEPROM_PAGE_LEN;        else            len = left;                if (do_write_i2c(fd, hi_adr, lo_adr + off, data + off, len) < 0)        {            PRINTF("EEPROM: page write error\n");            return -1;        }                usleep(10);        left -= len;        off += len;    }        return 0;}static int do_write_i2c(int fd, int hi_adr, int lo_adr,                        char *data, int length){    int i, ret;    char buf[EEPROM_PAGE_LEN + 1];        struct i2c_rdwr_ioctl_data i2c_data;        struct i2c_msg msgs;        if (length > EEPROM_PAGE_LEN)        return -1;        PRINTF("EEPROM: do write %d, %d, %d\n", hi_adr, lo_adr, length);        if (ioctl(fd, I2C_SLAVE_FORCE, eeprom_i2c_address | hi_adr) < 0)    {        PRINTF("EEPROM: set slave addr error %x, %x\n", hi_adr, lo_adr);        return -1;    }        /* if(write(fd, &lo_adr, 1) != 1) { PRINTF("EEPROM: write data error %x, %x\n", hi_adr,    lo_adr); return -1; } */    msgs.addr = eeprom_i2c_address | hi_adr;        msgs.flags = 0x00;        msgs.len = length + 1;        msgs.buf = buf;        i2c_data.nmsgs = 1;        i2c_data.msgs = &msgs;        buf[0] = lo_adr;        for (i = 1; i <= length; i++)    {        buf[i] = data[i - 1];    }    if (write(fd, buf, length + 1) != length + 1)    {        PRINTF("EEPROM: write data error %x, %x\n", hi_adr, lo_adr);        return -1;    }    return length;    /* ret = ioctl(fd, I2C_RDWR, (unsigned long*)(&i2c_data)); if(ret < 0) { PRINTF("EEPROM: write    data error %x, %x\n", hi_adr, lo_adr); return -1; } */}int eeprom_write(int fd, int sub_adr, unsigned char *data, int length){    int hi_adr = 0;    int lo_adr = 0;    int cur_adr;    int offset, left, len = 0;        if (sub_adr > EEPROM_MAX_ADDRESS)        return -1;        left = length;        offset = 0;        while (left)    {        cur_adr = sub_adr + offset;        hi_adr = cur_adr >> 8;        lo_adr = cur_adr & 0xff;        len = 0xff - lo_adr + 1;        PRINTF("EEPROM: eeprom write %d, %d, %d\n", hi_adr, lo_adr, len);                if (hi_adr > EEPROM_MAX_ADDRESS >> 8)            break;                if (len > left)            len = left;                if (i2c_page_write(fd, hi_adr, lo_adr, data + offset, len) < 0)            break;                left -= len;                offset += len;    }        return length - left;}int eeprom_read(int fd, int sub_adr, unsigned char *data, int length){    // write read address to eeprom    char hi_adr, lo_adr;    int ret, count = 0;    int i;    char buf;        struct i2c_rdwr_ioctl_data i2c_data;    struct i2c_msg msgs;        hi_adr = sub_adr >> 8;    lo_adr = sub_adr & 0xff;        PRINTF("ee_read: sub_adr = %x, hi_adr = %x, lo_adr = %x\n",        sub_adr, hi_adr, lo_adr);    if (ioctl(fd, I2C_SLAVE_FORCE, eeprom_i2c_address | hi_adr) < 0)    {        PRINTF("EEPROM: set slave addr error %x, %x\n", hi_adr, lo_adr);        return -1;    }        msgs.addr = eeprom_i2c_address | hi_adr;    msgs.flags = 0x00;    msgs.len = 1;    msgs.buf = &lo_adr;        i2c_data.nmsgs = 1;    i2c_data.msgs = &msgs;        /* ret = ioctl(fd, I2C_RDWR, (unsigned long *)(&i2c_data)); if(ret < 0) { PRINTF("EEPROM: write     data error %x, %x\n", hi_adr, lo_adr); return -1; } */        if (write(fd, &lo_adr, 1) != 1)    {        PRINTF("EEPROM: write data error %x, %x\n", hi_adr, lo_adr);        return -1;    }        /* for(i=0; i < length; i++) { ret = read(fd, data+i, 1); if(ret < 1) return count; count +=    ret; } */    return read(fd, data, length);}#elif defined(__DRV_FOR_VULCAN__)// xicor x24256int eeprom_write_begin(int fd){    return 0;}int eeprom_write_end(int fd){    return 0;}int eeprom_write(int fd, int sub_adr, unsigned char *data, int length){    int hi_adr = 0;    int lo_adr = 0;    int cur_adr;    int offset, left, len = 0, i;    char buf[EEPROM_PAGE_LEN + 2];        if (sub_adr < 0 || sub_adr > EEPROM_MAX_ADDRESS || length < 0)        return -1;        if(length + sub_adr > EEPROM_MAX_ADDRESS+1)        left = EEPROM_MAX_ADDRESS+1 - sub_adr;    else        left = length;        offset = 0;        while (left)    {        cur_adr = sub_adr + offset;        hi_adr = cur_adr >> 8;        lo_adr = cur_adr & 0xff;        len = EEPROM_PAGE_LEN - (lo_adr&(EEPROM_PAGE_LEN-1));        PRINTF("EEPROM: eeprom write hi_adr %d, lo_adr %d, len %d, left %d\n", hi_adr, lo_adr, len, left);                if (len > left)            len = left;                if (ioctl(fd, I2C_SLAVE_FORCE, eeprom_i2c_address) < 0)        {            PRINTF("EEPROM: set slave addr error %x, %x\n", hi_adr, lo_adr);            return -1;        }                buf[0] = hi_adr;        buf[1] = lo_adr;                for (i = 0; i < len; i++)        {            buf[i+2] = data[offset+i];        }                if (write(fd, buf, len + 2) != (len + 2) )        {            PRINTF("EEPROM: write data error 0x%x, 0x%x\n", hi_adr, lo_adr);            break;        }        left -= len;                offset += len;                //Dummy delay. The second write in loop does not succeed without this delay.        //Is I2C device not ready without the delay ?        for(i=0; i<50000; i++);    }        return offset;}int eeprom_read(int fd, int sub_adr, unsigned char *data, int length){    int hi_adr = 0;    int lo_adr = 0;    int cur_adr;    int offset, left, len = 0;    char buf[3];        struct i2c_rdwr_ioctl_data i2c_data;        struct i2c_msg msgs;        if (sub_adr < 0 || sub_adr > EEPROM_MAX_ADDRESS || length < 0)        return -1;        if(length + sub_adr > EEPROM_MAX_ADDRESS+1)        left = EEPROM_MAX_ADDRESS+1 - sub_adr;    else        left = length;        offset = 0;        while (left)    {        cur_adr = sub_adr + offset;        hi_adr = cur_adr >> 8;        lo_adr = cur_adr & 0xff;        PRINTF("EEPROM: eeprom read %d, %d, %d\n", hi_adr, lo_adr, left);                if (ioctl(fd, I2C_SLAVE_FORCE, eeprom_i2c_address) < 0)        {            PRINTF("EEPROM: set slave addr error 0x%x, 0x%x\n", hi_adr, lo_adr);            return -1;        }                buf[0] = hi_adr;        buf[1] = lo_adr;                if (write(fd, buf, 2) != 2)        {            PRINTF("EEPROM: set sub address error 0x%x, 0x%x\n", hi_adr, lo_adr);            break;        }                if (ioctl(fd, I2C_SLAVE_FORCE, eeprom_i2c_address) < 0)        {            PRINTF("EEPROM: set slave addr error 0x%x, 0x%x\n", hi_adr, lo_adr);            break;        }                len = read(fd, data+offset, left);        if(len <= 0)        {            PRINTF("EEPROM: failed to read addr %x, %x\n", hi_adr, lo_adr);            break;        }                left -= len;                offset += len;    }        return offset;}#else    #error "unknown architecture"#endif

⌨️ 快捷键说明

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