Path: blob/master/arch/cris/arch-v10/drivers/eeprom.c
15126 views
/*!*****************************************************************************1*!2*! Implements an interface for i2c compatible eeproms to run under Linux.3*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustments by4*! [email protected]5*!6*! Probing results:7*! 8k or not is detected (the assumes 2k or 16k)8*! 2k or 16k detected using test reads and writes.9*!10*!------------------------------------------------------------------------11*! HISTORY12*!13*! DATE NAME CHANGES14*! ---- ---- -------15*! Aug 28 1999 Edgar Iglesias Initial Version16*! Aug 31 1999 Edgar Iglesias Allow simultaneous users.17*! Sep 03 1999 Edgar Iglesias Updated probe.18*! Sep 03 1999 Edgar Iglesias Added bail-out stuff if we get interrupted19*! in the spin-lock.20*!21*! (c) 1999 Axis Communications AB, Lund, Sweden22*!*****************************************************************************/2324#include <linux/kernel.h>25#include <linux/sched.h>26#include <linux/fs.h>27#include <linux/init.h>28#include <linux/delay.h>29#include <linux/interrupt.h>30#include <linux/wait.h>31#include <asm/uaccess.h>32#include "i2c.h"3334#define D(x)3536/* If we should use adaptive timing or not: */37/* #define EEPROM_ADAPTIVE_TIMING */3839#define EEPROM_MAJOR_NR 122 /* use a LOCAL/EXPERIMENTAL major for now */40#define EEPROM_MINOR_NR 04142/* Empirical sane initial value of the delay, the value will be adapted to43* what the chip needs when using EEPROM_ADAPTIVE_TIMING.44*/45#define INITIAL_WRITEDELAY_US 400046#define MAX_WRITEDELAY_US 10000 /* 10 ms according to spec for 2KB EEPROM */4748/* This one defines how many times to try when eeprom fails. */49#define EEPROM_RETRIES 105051#define EEPROM_2KB (2 * 1024)52/*#define EEPROM_4KB (4 * 1024)*/ /* Exists but not used in Axis products */53#define EEPROM_8KB (8 * 1024 - 1 ) /* Last byte has write protection bit */54#define EEPROM_16KB (16 * 1024)5556#define i2c_delay(x) udelay(x)5758/*59* This structure describes the attached eeprom chip.60* The values are probed for.61*/6263struct eeprom_type64{65unsigned long size;66unsigned long sequential_write_pagesize;67unsigned char select_cmd;68unsigned long usec_delay_writecycles; /* Min time between write cycles69(up to 10ms for some models) */70unsigned long usec_delay_step; /* For adaptive algorithm */71int adapt_state; /* 1 = To high , 0 = Even, -1 = To low */7273/* this one is to keep the read/write operations atomic */74struct mutex lock;75int retry_cnt_addr; /* Used to keep track of number of retries for76adaptive timing adjustments */77int retry_cnt_read;78};7980static int eeprom_open(struct inode * inode, struct file * file);81static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig);82static ssize_t eeprom_read(struct file * file, char * buf, size_t count,83loff_t *off);84static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,85loff_t *off);86static int eeprom_close(struct inode * inode, struct file * file);8788static int eeprom_address(unsigned long addr);89static int read_from_eeprom(char * buf, int count);90static int eeprom_write_buf(loff_t addr, const char * buf, int count);91static int eeprom_read_buf(loff_t addr, char * buf, int count);9293static void eeprom_disable_write_protect(void);949596static const char eeprom_name[] = "eeprom";9798/* chip description */99static struct eeprom_type eeprom;100101/* This is the exported file-operations structure for this device. */102const struct file_operations eeprom_fops =103{104.llseek = eeprom_lseek,105.read = eeprom_read,106.write = eeprom_write,107.open = eeprom_open,108.release = eeprom_close109};110111/* eeprom init call. Probes for different eeprom models. */112113int __init eeprom_init(void)114{115mutex_init(&eeprom.lock);116117#ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE118#define EETEXT "Found"119#else120#define EETEXT "Assuming"121#endif122if (register_chrdev(EEPROM_MAJOR_NR, eeprom_name, &eeprom_fops))123{124printk(KERN_INFO "%s: unable to get major %d for eeprom device\n",125eeprom_name, EEPROM_MAJOR_NR);126return -1;127}128129printk("EEPROM char device v0.3, (c) 2000 Axis Communications AB\n");130131/*132* Note: Most of this probing method was taken from the printserver (5470e)133* codebase. It did not contain a way of finding the 16kB chips134* (M24128 or variants). The method used here might not work135* for all models. If you encounter problems the easiest way136* is probably to define your model within #ifdef's, and hard-137* code it.138*/139140eeprom.size = 0;141eeprom.usec_delay_writecycles = INITIAL_WRITEDELAY_US;142eeprom.usec_delay_step = 128;143eeprom.adapt_state = 0;144145#ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE146i2c_start();147i2c_outbyte(0x80);148if(!i2c_getack())149{150/* It's not 8k.. */151int success = 0;152unsigned char buf_2k_start[16];153154/* Im not sure this will work... :) */155/* assume 2kB, if failure go for 16kB */156/* Test with 16kB settings.. */157/* If it's a 2kB EEPROM and we address it outside it's range158* it will mirror the address space:159* 1. We read two locations (that are mirrored),160* if the content differs * it's a 16kB EEPROM.161* 2. if it doesn't differ - write different value to one of the locations,162* check the other - if content still is the same it's a 2k EEPROM,163* restore original data.164*/165#define LOC1 8166#define LOC2 (0x1fb) /*1fb, 3ed, 5df, 7d1 */167168/* 2k settings */169i2c_stop();170eeprom.size = EEPROM_2KB;171eeprom.select_cmd = 0xA0;172eeprom.sequential_write_pagesize = 16;173if( eeprom_read_buf( 0, buf_2k_start, 16 ) == 16 )174{175D(printk("2k start: '%16.16s'\n", buf_2k_start));176}177else178{179printk(KERN_INFO "%s: Failed to read in 2k mode!\n", eeprom_name);180}181182/* 16k settings */183eeprom.size = EEPROM_16KB;184eeprom.select_cmd = 0xA0;185eeprom.sequential_write_pagesize = 64;186187{188unsigned char loc1[4], loc2[4], tmp[4];189if( eeprom_read_buf(LOC2, loc2, 4) == 4)190{191if( eeprom_read_buf(LOC1, loc1, 4) == 4)192{193D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n",194LOC1, loc1, LOC2, loc2));195#if 0196if (memcmp(loc1, loc2, 4) != 0 )197{198/* It's 16k */199printk(KERN_INFO "%s: 16k detected in step 1\n", eeprom_name);200eeprom.size = EEPROM_16KB;201success = 1;202}203else204#endif205{206/* Do step 2 check */207/* Invert value */208loc1[0] = ~loc1[0];209if (eeprom_write_buf(LOC1, loc1, 1) == 1)210{211/* If 2k EEPROM this write will actually write 10 bytes212* from pos 0213*/214D(printk("1 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n",215LOC1, loc1, LOC2, loc2));216if( eeprom_read_buf(LOC1, tmp, 4) == 4)217{218D(printk("2 loc1: (%i) '%4.4s' tmp '%4.4s'\n",219LOC1, loc1, tmp));220if (memcmp(loc1, tmp, 4) != 0 )221{222printk(KERN_INFO "%s: read and write differs! Not 16kB\n",223eeprom_name);224loc1[0] = ~loc1[0];225226if (eeprom_write_buf(LOC1, loc1, 1) == 1)227{228success = 1;229}230else231{232printk(KERN_INFO "%s: Restore 2k failed during probe,"233" EEPROM might be corrupt!\n", eeprom_name);234235}236i2c_stop();237/* Go to 2k mode and write original data */238eeprom.size = EEPROM_2KB;239eeprom.select_cmd = 0xA0;240eeprom.sequential_write_pagesize = 16;241if( eeprom_write_buf(0, buf_2k_start, 16) == 16)242{243}244else245{246printk(KERN_INFO "%s: Failed to write back 2k start!\n",247eeprom_name);248}249250eeprom.size = EEPROM_2KB;251}252}253254if(!success)255{256if( eeprom_read_buf(LOC2, loc2, 1) == 1)257{258D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n",259LOC1, loc1, LOC2, loc2));260if (memcmp(loc1, loc2, 4) == 0 )261{262/* Data the same, must be mirrored -> 2k */263/* Restore data */264printk(KERN_INFO "%s: 2k detected in step 2\n", eeprom_name);265loc1[0] = ~loc1[0];266if (eeprom_write_buf(LOC1, loc1, 1) == 1)267{268success = 1;269}270else271{272printk(KERN_INFO "%s: Restore 2k failed during probe,"273" EEPROM might be corrupt!\n", eeprom_name);274275}276277eeprom.size = EEPROM_2KB;278}279else280{281printk(KERN_INFO "%s: 16k detected in step 2\n",282eeprom_name);283loc1[0] = ~loc1[0];284/* Data differs, assume 16k */285/* Restore data */286if (eeprom_write_buf(LOC1, loc1, 1) == 1)287{288success = 1;289}290else291{292printk(KERN_INFO "%s: Restore 16k failed during probe,"293" EEPROM might be corrupt!\n", eeprom_name);294}295296eeprom.size = EEPROM_16KB;297}298}299}300}301} /* read LOC1 */302} /* address LOC1 */303if (!success)304{305printk(KERN_INFO "%s: Probing failed!, using 2KB!\n", eeprom_name);306eeprom.size = EEPROM_2KB;307}308} /* read */309}310}311else312{313i2c_outbyte(0x00);314if(!i2c_getack())315{316/* No 8k */317eeprom.size = EEPROM_2KB;318}319else320{321i2c_start();322i2c_outbyte(0x81);323if (!i2c_getack())324{325eeprom.size = EEPROM_2KB;326}327else328{329/* It's a 8kB */330i2c_inbyte();331eeprom.size = EEPROM_8KB;332}333}334}335i2c_stop();336#elif defined(CONFIG_ETRAX_I2C_EEPROM_16KB)337eeprom.size = EEPROM_16KB;338#elif defined(CONFIG_ETRAX_I2C_EEPROM_8KB)339eeprom.size = EEPROM_8KB;340#elif defined(CONFIG_ETRAX_I2C_EEPROM_2KB)341eeprom.size = EEPROM_2KB;342#endif343344switch(eeprom.size)345{346case (EEPROM_2KB):347printk("%s: " EETEXT " i2c compatible 2kB eeprom.\n", eeprom_name);348eeprom.sequential_write_pagesize = 16;349eeprom.select_cmd = 0xA0;350break;351case (EEPROM_8KB):352printk("%s: " EETEXT " i2c compatible 8kB eeprom.\n", eeprom_name);353eeprom.sequential_write_pagesize = 16;354eeprom.select_cmd = 0x80;355break;356case (EEPROM_16KB):357printk("%s: " EETEXT " i2c compatible 16kB eeprom.\n", eeprom_name);358eeprom.sequential_write_pagesize = 64;359eeprom.select_cmd = 0xA0;360break;361default:362eeprom.size = 0;363printk("%s: Did not find a supported eeprom\n", eeprom_name);364break;365}366367368369eeprom_disable_write_protect();370371return 0;372}373374/* Opens the device. */375static int eeprom_open(struct inode * inode, struct file * file)376{377if(iminor(inode) != EEPROM_MINOR_NR)378return -ENXIO;379if(imajor(inode) != EEPROM_MAJOR_NR)380return -ENXIO;381382if( eeprom.size > 0 )383{384/* OK */385return 0;386}387388/* No EEprom found */389return -EFAULT;390}391392/* Changes the current file position. */393394static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig)395{396/*397* orig 0: position from begning of eeprom398* orig 1: relative from current position399* orig 2: position from last eeprom address400*/401402switch (orig)403{404case 0:405file->f_pos = offset;406break;407case 1:408file->f_pos += offset;409break;410case 2:411file->f_pos = eeprom.size - offset;412break;413default:414return -EINVAL;415}416417/* truncate position */418if (file->f_pos < 0)419{420file->f_pos = 0;421return(-EOVERFLOW);422}423424if (file->f_pos >= eeprom.size)425{426file->f_pos = eeprom.size - 1;427return(-EOVERFLOW);428}429430return ( file->f_pos );431}432433/* Reads data from eeprom. */434435static int eeprom_read_buf(loff_t addr, char * buf, int count)436{437return eeprom_read(NULL, buf, count, &addr);438}439440441442/* Reads data from eeprom. */443444static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t *off)445{446int read=0;447unsigned long p = *off;448449unsigned char page;450451if(p >= eeprom.size) /* Address i 0 - (size-1) */452{453return -EFAULT;454}455456if (mutex_lock_interruptible(&eeprom.lock))457return -EINTR;458459page = (unsigned char) (p >> 8);460461if(!eeprom_address(p))462{463printk(KERN_INFO "%s: Read failed to address the eeprom: "464"0x%08X (%i) page: %i\n", eeprom_name, (int)p, (int)p, page);465i2c_stop();466467/* don't forget to wake them up */468mutex_unlock(&eeprom.lock);469return -EFAULT;470}471472if( (p + count) > eeprom.size)473{474/* truncate count */475count = eeprom.size - p;476}477478/* stop dummy write op and initiate the read op */479i2c_start();480481/* special case for small eeproms */482if(eeprom.size < EEPROM_16KB)483{484i2c_outbyte( eeprom.select_cmd | 1 | (page << 1) );485}486487/* go on with the actual read */488read = read_from_eeprom( buf, count);489490if(read > 0)491{492*off += read;493}494495mutex_unlock(&eeprom.lock);496return read;497}498499/* Writes data to eeprom. */500501static int eeprom_write_buf(loff_t addr, const char * buf, int count)502{503return eeprom_write(NULL, buf, count, &addr);504}505506507/* Writes data to eeprom. */508509static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,510loff_t *off)511{512int i, written, restart=1;513unsigned long p;514515if (!access_ok(VERIFY_READ, buf, count))516{517return -EFAULT;518}519520/* bail out if we get interrupted */521if (mutex_lock_interruptible(&eeprom.lock))522return -EINTR;523for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++)524{525restart = 0;526written = 0;527p = *off;528529530while( (written < count) && (p < eeprom.size))531{532/* address the eeprom */533if(!eeprom_address(p))534{535printk(KERN_INFO "%s: Write failed to address the eeprom: "536"0x%08X (%i) \n", eeprom_name, (int)p, (int)p);537i2c_stop();538539/* don't forget to wake them up */540mutex_unlock(&eeprom.lock);541return -EFAULT;542}543#ifdef EEPROM_ADAPTIVE_TIMING544/* Adaptive algorithm to adjust timing */545if (eeprom.retry_cnt_addr > 0)546{547/* To Low now */548D(printk(">D=%i d=%i\n",549eeprom.usec_delay_writecycles, eeprom.usec_delay_step));550551if (eeprom.usec_delay_step < 4)552{553eeprom.usec_delay_step++;554eeprom.usec_delay_writecycles += eeprom.usec_delay_step;555}556else557{558559if (eeprom.adapt_state > 0)560{561/* To Low before */562eeprom.usec_delay_step *= 2;563if (eeprom.usec_delay_step > 2)564{565eeprom.usec_delay_step--;566}567eeprom.usec_delay_writecycles += eeprom.usec_delay_step;568}569else if (eeprom.adapt_state < 0)570{571/* To High before (toggle dir) */572eeprom.usec_delay_writecycles += eeprom.usec_delay_step;573if (eeprom.usec_delay_step > 1)574{575eeprom.usec_delay_step /= 2;576eeprom.usec_delay_step--;577}578}579}580581eeprom.adapt_state = 1;582}583else584{585/* To High (or good) now */586D(printk("<D=%i d=%i\n",587eeprom.usec_delay_writecycles, eeprom.usec_delay_step));588589if (eeprom.adapt_state < 0)590{591/* To High before */592if (eeprom.usec_delay_step > 1)593{594eeprom.usec_delay_step *= 2;595eeprom.usec_delay_step--;596597if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step)598{599eeprom.usec_delay_writecycles -= eeprom.usec_delay_step;600}601}602}603else if (eeprom.adapt_state > 0)604{605/* To Low before (toggle dir) */606if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step)607{608eeprom.usec_delay_writecycles -= eeprom.usec_delay_step;609}610if (eeprom.usec_delay_step > 1)611{612eeprom.usec_delay_step /= 2;613eeprom.usec_delay_step--;614}615616eeprom.adapt_state = -1;617}618619if (eeprom.adapt_state > -100)620{621eeprom.adapt_state--;622}623else624{625/* Restart adaption */626D(printk("#Restart\n"));627eeprom.usec_delay_step++;628}629}630#endif /* EEPROM_ADAPTIVE_TIMING */631/* write until we hit a page boundary or count */632do633{634i2c_outbyte(buf[written]);635if(!i2c_getack())636{637restart=1;638printk(KERN_INFO "%s: write error, retrying. %d\n", eeprom_name, i);639i2c_stop();640break;641}642written++;643p++;644} while( written < count && ( p % eeprom.sequential_write_pagesize ));645646/* end write cycle */647i2c_stop();648i2c_delay(eeprom.usec_delay_writecycles);649} /* while */650} /* for */651652mutex_unlock(&eeprom.lock);653if (written == 0 && p >= eeprom.size){654return -ENOSPC;655}656*off = p;657return written;658}659660/* Closes the device. */661662static int eeprom_close(struct inode * inode, struct file * file)663{664/* do nothing for now */665return 0;666}667668/* Sets the current address of the eeprom. */669670static int eeprom_address(unsigned long addr)671{672int i;673unsigned char page, offset;674675page = (unsigned char) (addr >> 8);676offset = (unsigned char) addr;677678for(i = 0; i < EEPROM_RETRIES; i++)679{680/* start a dummy write for addressing */681i2c_start();682683if(eeprom.size == EEPROM_16KB)684{685i2c_outbyte( eeprom.select_cmd );686i2c_getack();687i2c_outbyte(page);688}689else690{691i2c_outbyte( eeprom.select_cmd | (page << 1) );692}693if(!i2c_getack())694{695/* retry */696i2c_stop();697/* Must have a delay here.. 500 works, >50, 100->works 5th time*/698i2c_delay(MAX_WRITEDELAY_US / EEPROM_RETRIES * i);699/* The chip needs up to 10 ms from write stop to next start */700701}702else703{704i2c_outbyte(offset);705706if(!i2c_getack())707{708/* retry */709i2c_stop();710}711else712break;713}714}715716717eeprom.retry_cnt_addr = i;718D(printk("%i\n", eeprom.retry_cnt_addr));719if(eeprom.retry_cnt_addr == EEPROM_RETRIES)720{721/* failed */722return 0;723}724return 1;725}726727/* Reads from current address. */728729static int read_from_eeprom(char * buf, int count)730{731int i, read=0;732733for(i = 0; i < EEPROM_RETRIES; i++)734{735if(eeprom.size == EEPROM_16KB)736{737i2c_outbyte( eeprom.select_cmd | 1 );738}739740if(i2c_getack())741{742break;743}744}745746if(i == EEPROM_RETRIES)747{748printk(KERN_INFO "%s: failed to read from eeprom\n", eeprom_name);749i2c_stop();750751return -EFAULT;752}753754while( (read < count))755{756if (put_user(i2c_inbyte(), &buf[read++]))757{758i2c_stop();759760return -EFAULT;761}762763/*764* make sure we don't ack last byte or you will get very strange765* results!766*/767if(read < count)768{769i2c_sendack();770}771}772773/* stop the operation */774i2c_stop();775776return read;777}778779/* Disables write protection if applicable. */780781#define DBP_SAVE(x)782#define ax_printf printk783static void eeprom_disable_write_protect(void)784{785/* Disable write protect */786if (eeprom.size == EEPROM_8KB)787{788/* Step 1 Set WEL = 1 (write 00000010 to address 1FFFh */789i2c_start();790i2c_outbyte(0xbe);791if(!i2c_getack())792{793DBP_SAVE(ax_printf("Get ack returns false\n"));794}795i2c_outbyte(0xFF);796if(!i2c_getack())797{798DBP_SAVE(ax_printf("Get ack returns false 2\n"));799}800i2c_outbyte(0x02);801if(!i2c_getack())802{803DBP_SAVE(ax_printf("Get ack returns false 3\n"));804}805i2c_stop();806807i2c_delay(1000);808809/* Step 2 Set RWEL = 1 (write 00000110 to address 1FFFh */810i2c_start();811i2c_outbyte(0xbe);812if(!i2c_getack())813{814DBP_SAVE(ax_printf("Get ack returns false 55\n"));815}816i2c_outbyte(0xFF);817if(!i2c_getack())818{819DBP_SAVE(ax_printf("Get ack returns false 52\n"));820}821i2c_outbyte(0x06);822if(!i2c_getack())823{824DBP_SAVE(ax_printf("Get ack returns false 53\n"));825}826i2c_stop();827828/* Step 3 Set BP1, BP0, and/or WPEN bits (write 00000110 to address 1FFFh */829i2c_start();830i2c_outbyte(0xbe);831if(!i2c_getack())832{833DBP_SAVE(ax_printf("Get ack returns false 56\n"));834}835i2c_outbyte(0xFF);836if(!i2c_getack())837{838DBP_SAVE(ax_printf("Get ack returns false 57\n"));839}840i2c_outbyte(0x06);841if(!i2c_getack())842{843DBP_SAVE(ax_printf("Get ack returns false 58\n"));844}845i2c_stop();846847/* Write protect disabled */848}849}850851module_init(eeprom_init);852853854