mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-11-03 13:38:25 +00:00
(Phil) Yikes! Removing the i2c project from lm_sensors2. The new home is
in the root dir of the CVS archive. (a complete backup was made before doing this, of course ;') git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@489 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
9f20e1e821
commit
bcb6b86014
30 files changed
-4315
No files matched your search
@@ -1,61 +0,0 @@
|
||||
This is a list of modifications between the stock i2c code as distributed
|
||||
by Simon Vogl, and the code included in and beneath this directory. None
|
||||
of these changes are important; you can still use a self-compiled version
|
||||
of the i2c code and not compile the version in here.
|
||||
|
||||
! Changes marked with an exclamation mark *are* important, and *must*
|
||||
be applied! If there are changes like this in this list, you *must*
|
||||
use our version of the i2c module!
|
||||
|
||||
The current version of Simon's code is called mod-19990118.tar.gz.
|
||||
|
||||
Here come the changes:
|
||||
|
||||
* Added I2C_DRIVERID_BT848 in i2c.h
|
||||
|
||||
! Changed line 2 of algo-bit.h from AGLO_BIT_H to ALGO_BIT_H
|
||||
|
||||
! Fixed i2c_probe bug
|
||||
|
||||
! Changed to init_MUTEX and a compatibility line in i2c-core.c
|
||||
|
||||
! i2c.h now includes <linux/schedule.h> instead of <asm/semaphore.h> for old
|
||||
2.0 kernels
|
||||
|
||||
* Algo-bit now scans the bus before registering the adapter.
|
||||
|
||||
* Bit-lp and bit-velle don't increase module usage counts
|
||||
when clients register.
|
||||
|
||||
! Renamed #define HW_B_MB to HW_B_VIA in i2c.h
|
||||
|
||||
! Added '#include <linux/page.h>' to i2c.h, to make it compile with 2.2
|
||||
kernels.
|
||||
|
||||
* Moved files: bit-via.c and README.bit-via
|
||||
These are now under lm_sensors source tree as
|
||||
kernel/busses/i2c-via.c and doc/busses/i2c-via
|
||||
|
||||
* EXPORT_SYMBOL declarations put between #ifdef statements
|
||||
They only work if you use the Linux source tree Makefiles. As we want to
|
||||
use our own Makefile, we have removed them. This should have almost no
|
||||
influence on the resulting object code; a few more functions may be
|
||||
exported, but this should do no harm.
|
||||
|
||||
# Made i2c-core a bit quieter
|
||||
|
||||
* New file: Module.mk
|
||||
The Makefile fragment we use to compile the files in this directory.
|
||||
|
||||
* New file: MODIFICATIONS
|
||||
The file you are reading right now.
|
||||
|
||||
* Removed files: object files and executables
|
||||
Everywhere, remakeable files are removed, to keep the source distribution
|
||||
small and lean.
|
||||
|
||||
* algo-bit.h: Removed comment typo (Geert)
|
||||
|
||||
* bit-lp.c: Added #include <linux/stddef> (Geert)
|
||||
|
||||
* i2c.h: Added HW_B_HYDRA, removed two comment typos (Geert)
|
||||
@@ -1,40 +0,0 @@
|
||||
#################################################
|
||||
# config
|
||||
KERNEL_LOCATION=/usr/src/linux
|
||||
CURRENT=$(shell uname -r)
|
||||
|
||||
#################################################
|
||||
# some magic for using linux kernel settings
|
||||
# when compiling module(s)
|
||||
|
||||
MOD_SUB_DIRS = drivers
|
||||
#MX_OBJS = i2c-core.o algo-bit.o i2c-dev.o bit-lp.o bit-velle.o algo-pcf.o
|
||||
MX_OBJS = i2c-core.o algo-bit.o i2c-dev.o
|
||||
|
||||
M_OBJS = bit-lp.o bit-velle.o
|
||||
EXTRA_CFLAGS = -Wno-unused
|
||||
|
||||
here:
|
||||
DIR=`pwd`; (cd $(KERNEL_LOCATION); make SUBDIRS=$$DIR modules)
|
||||
|
||||
install:
|
||||
su -c "cp -v $(M_OBJS) $(MX_OBJS) /lib/modules/$(CURRENT)/misc"
|
||||
|
||||
clean:
|
||||
-rm -f $(M_OBJS) $(MX_OBJS) .*.o.flags *~
|
||||
|
||||
up:
|
||||
insmod i2c-core.o i2c_debug=0
|
||||
insmod algo-bit.o bit_test=1 i2c_debug=1
|
||||
insmod bit-lp.o base=0x278
|
||||
insmod i2c-dev.o
|
||||
insmod drivers/eeprom.o test=1
|
||||
|
||||
down:
|
||||
-rmmod eeprom
|
||||
-rmmod i2c-dev
|
||||
-rmmod bit-lp
|
||||
-rmmod algo-bit
|
||||
-rmmod i2c-core
|
||||
|
||||
include $(KERNEL_LOCATION)/Rules.make
|
||||
@@ -1,47 +0,0 @@
|
||||
# Module.mk - Makefile for a Linux module for reading sensor data.
|
||||
# Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Note that MODULE_DIR (the directory in which this file resides) is a
|
||||
# 'simply expanded variable'. That means that its value is substituted
|
||||
# verbatim in the rules, until it is redefined.
|
||||
MODULE_DIR := i2c
|
||||
|
||||
# Regrettably, even 'simply expanded variables' will not put their currently
|
||||
# defined value verbatim into the command-list of rules...
|
||||
I2CTARGETS := $(MODULE_DIR)/i2c-core.o $(MODULE_DIR)/algo-bit.o \
|
||||
$(MODULE_DIR)/bit-lp.o $(MODULE_DIR)/bit-velle.o
|
||||
|
||||
I2CADDTARGETS := $(MODULE_DIR)/i2c-dev.o
|
||||
|
||||
I2CHEADERFILES := $(MODULE_DIR)/i2c.h
|
||||
|
||||
# Include all dependency files
|
||||
INCLUDEFILES += $(I2CTARGETS:.o=.d)
|
||||
|
||||
all-i2c: $(I2CTARGETS) $(I2CADDTARGETS)
|
||||
all :: all-i2c
|
||||
|
||||
install-i2c: all-i2c
|
||||
$(MKDIR) $(MODDIR) $(SYSINCLUDEDIR)
|
||||
$(INSTALL) -o root -g root -m 644 $(I2CTARGETS) $(MODDIR)
|
||||
$(INSTALL) -o root -g root -m 644 $(I2CHEADERFILES) $(SYSINCLUDEDIR)
|
||||
install :: install-i2c
|
||||
|
||||
clean-i2c:
|
||||
$(RM) $(I2CTARGETS) $(I2CTARGETS:.o=.d) $(I2CADDTARGETS) \
|
||||
$(I2CADDTARGETS:.o=.d)
|
||||
clean :: clean-i2c
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
Okay, a new version is born...
|
||||
There are still many files from the old version lying around that
|
||||
need to be ported - anyone have spare time ?
|
||||
|
||||
Currently, the following modules are running in the new mode:
|
||||
i2c.c - main admin module & common interface
|
||||
i2c-dev.c - character device interface for the bus
|
||||
algo-bit.c - Algorithms for bit banging
|
||||
bit-lp.c - hw part for parallel port adapter, Philips interface
|
||||
bit-velle.c - hw part for parallel port adapter, Vellemann K9000
|
||||
|
||||
The other modules, esp. algo-pcf.c still need to be converted. For the
|
||||
hw specific mods, this should be relatively easy & quick.
|
||||
|
||||
*
|
||||
* NOTE: The algo-pcf part is currently in the works, thanks to Hans Berglund
|
||||
* (hb@mailhost.spacetec.no).
|
||||
*
|
||||
|
||||
A simple driver example is in drivers -- a piece of code to access EEPROMs.
|
||||
|
||||
Simon (simon@tk.uni-linz.ac.at)
|
||||
|
||||
For more detailed documentation have a look at
|
||||
http://www.tk.uni-linz.ac.at/~simon/private/i2c
|
||||
|
||||
-659
@@ -1,659 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* adap-bit.c i2c driver algorithms for bit-shift adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char alg_rcsid[] = "$Id: algo-bit.c,v 1.8 1998/12/30 08:36:08 i2c Exp i2c $";
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
# include <asm/uaccess.h>
|
||||
#else
|
||||
# include <asm/segment.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "algo-bit.h"
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) if (i2c_debug>=1) x;
|
||||
#define DEB2(x) if (i2c_debug>=2) x;
|
||||
#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
|
||||
#define DEBPROTO(x) if (i2c_debug>=9) x;
|
||||
/* debug the protocol by showing transferred bits */
|
||||
|
||||
/* debugging - slow down transfer to have a look at the data .. */
|
||||
/* I use this with two leds&resistors, each one connected to sda,scl */
|
||||
/* respectively. This makes sure that the algorithm works. Some chips */
|
||||
/* might not like this, as they have an internal timeout of some mils */
|
||||
/*
|
||||
#if LINUX_VERSION_CODE >= 0x02016e
|
||||
#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
|
||||
if (need_resched) schedule();
|
||||
#else
|
||||
#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
|
||||
if (need_resched) schedule();
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
/* ----- global variables --------------------------------------------- */
|
||||
|
||||
#ifdef SLO_IO
|
||||
int jif;
|
||||
#endif
|
||||
|
||||
/* module parameters:
|
||||
*/
|
||||
int i2c_debug=1;
|
||||
int bit_test=0; /* see if the line-setting functions work */
|
||||
int bit_scan=0; /* have a look at what's hanging 'round */
|
||||
|
||||
/*
|
||||
* This array contains the hw-specific functions for
|
||||
* each port (hardware) type.
|
||||
*/
|
||||
struct bit_adapter *bit_adaps[BIT_ADAP_MAX];
|
||||
int adap_count;
|
||||
struct i2c_adapter *i2c_adaps[BIT_ADAP_MAX];
|
||||
|
||||
/* --- setting states on the bus with the right timing: --------------- */
|
||||
|
||||
#define setsda(adap,val) adap->setsda(adap->data, val)
|
||||
#define setscl(adap,val) adap->setscl(adap->data, val)
|
||||
#define getsda(adap) adap->getsda(adap->data)
|
||||
#define getscl(adap) adap->getscl(adap->data)
|
||||
|
||||
inline void sdalo(struct bit_adapter *adap)
|
||||
{
|
||||
setsda(adap,0);
|
||||
udelay(adap->udelay);
|
||||
}
|
||||
|
||||
inline void sdahi(struct bit_adapter *adap)
|
||||
{
|
||||
setsda(adap,1);
|
||||
udelay(adap->udelay);
|
||||
}
|
||||
|
||||
inline void scllo(struct bit_adapter *adap)
|
||||
{
|
||||
setscl(adap,0);
|
||||
udelay(adap->udelay);
|
||||
#ifdef SLO_IO
|
||||
SLO_IO
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Raise scl line, and do checking for delays. This is necessary for slower
|
||||
* devices.
|
||||
*/
|
||||
inline int sclhi(struct bit_adapter *adap)
|
||||
{
|
||||
int start=jiffies;
|
||||
|
||||
setscl(adap,1);
|
||||
|
||||
udelay(adap->udelay);
|
||||
if (adap->getscl == NULL )
|
||||
return 0;
|
||||
while (! getscl(adap) ) {
|
||||
/* the hw knows how to read the clock line,
|
||||
* so we wait until it actually gets high.
|
||||
* This is safer as some chips may hold it low
|
||||
* while they are processing data internally.
|
||||
*/
|
||||
setscl(adap,1);
|
||||
if (start+adap->timeout <= jiffies) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= 0x02016e
|
||||
if (current->need_resched)
|
||||
schedule();
|
||||
#else
|
||||
if (need_resched)
|
||||
schedule();
|
||||
#endif
|
||||
}
|
||||
DEBSTAT(printk("needed %ld jiffies\n", jiffies-start));
|
||||
#ifdef SLO_IO
|
||||
SLO_IO
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* --- other auxiliary functions -------------------------------------- */
|
||||
void i2c_start(struct bit_adapter *adap)
|
||||
{
|
||||
/* assert: scl, sda are high */
|
||||
DEBPROTO(printk("S "));
|
||||
sdalo(adap);
|
||||
scllo(adap);
|
||||
}
|
||||
|
||||
void i2c_repstart(struct bit_adapter *adap)
|
||||
{
|
||||
/* scl, sda may not be high */
|
||||
DEBPROTO(printk(" Sr "));
|
||||
setsda(adap,1);
|
||||
setscl(adap,1);
|
||||
udelay(adap->udelay);
|
||||
|
||||
sdalo(adap);
|
||||
scllo(adap);
|
||||
}
|
||||
|
||||
|
||||
void i2c_stop(struct bit_adapter *adap)
|
||||
{
|
||||
DEBPROTO(printk("P\n"));
|
||||
/* assert: scl is low */
|
||||
sdalo(adap);
|
||||
sclhi(adap);
|
||||
sdahi(adap);
|
||||
}
|
||||
|
||||
/* send a byte without start cond., look for arbitration,
|
||||
check ackn. from slave */
|
||||
/* return 1 if ok */
|
||||
int i2c_outb(struct bit_adapter *adap, char c)
|
||||
{
|
||||
int i;
|
||||
int sb;
|
||||
int ack;
|
||||
|
||||
/* assert: scl is low */
|
||||
DEB2(printk(" i2c_outb:%2.2X\n",c&0xff));
|
||||
for ( i=7 ; i>=0 ; i-- ) {
|
||||
sb = c & ( 1 << i );
|
||||
setsda(adap,sb);
|
||||
udelay(adap->udelay);
|
||||
DEBPROTO(printk("%d",sb!=0));
|
||||
if (sclhi(adap)<0) { /* timed out */
|
||||
sdahi(adap); /* we don't want to block the net */
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
/* do arbitration here:
|
||||
* if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
|
||||
*/
|
||||
setscl( adap, 0 );
|
||||
udelay(adap->udelay);
|
||||
}
|
||||
sdahi(adap);
|
||||
if (sclhi(adap)<0){ /* timeout */
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
/* read ack: SDA should be pulled down by slave */
|
||||
ack=getsda(adap); /* ack: sda is pulled low ->success. */
|
||||
DEB2(printk(" i2c_outb: getsda() = 0x%2.2x\n", ~ack ));
|
||||
|
||||
DEBPROTO( printk("[%2.2x]",c&0xff) );
|
||||
DEBPROTO(if (0==ack) printk(" A "); else printk(" NA ") );
|
||||
scllo(adap);
|
||||
return 0==ack; /* return 1 if device acked */
|
||||
/* assert: scl is low (sda undef) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
int i2c_inb(struct bit_adapter *adap)
|
||||
{
|
||||
/* read byte via i2c port, without start/stop sequence */
|
||||
/* acknowledge is sent in i2c_read. */
|
||||
int i;
|
||||
char indata;
|
||||
|
||||
/* assert: scl is low */
|
||||
DEB2(printk("i2c_inb.\n"));
|
||||
|
||||
sdahi(adap);
|
||||
indata=0;
|
||||
for (i=0;i<8;i++) {
|
||||
if (sclhi(adap)<0) { /* timeout */
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
indata *= 2;
|
||||
if ( getsda(adap) )
|
||||
indata |= 0x01;
|
||||
scllo(adap);
|
||||
}
|
||||
/* assert: scl is low */
|
||||
DEBPROTO(printk(" %2.2x", indata & 0xff));
|
||||
return (int) (indata & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check for the adapter hardware - check the reaction of
|
||||
* the bus lines only if it seems to be idle.
|
||||
*/
|
||||
int test_bus(struct bit_adapter *adap) {
|
||||
int scl,sda;
|
||||
sda=getsda(adap);
|
||||
if (adap->getscl==NULL) {
|
||||
printk("i2c(bit): Warning: Adapter can't read from clock line - skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
scl=getscl(adap);
|
||||
printk("i2c(bit): Adapter: %s scl: %d sda: %d -- testing...\n",
|
||||
adap->name,getscl(adap),getsda(adap));
|
||||
if (!scl || !sda ) {
|
||||
printk("i2c(bit): %s seems to be busy.\n",adap->name);
|
||||
goto bailout;
|
||||
}
|
||||
sdalo(adap);
|
||||
printk("i2c(bit):1 scl: %d sda: %d \n",getscl(adap),getsda(adap));
|
||||
if ( 0 != getsda(adap) ) {
|
||||
printk("i2c(bit): %s SDA stuck high!\n",adap->name);
|
||||
sdahi(adap);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == getscl(adap) ) {
|
||||
printk("i2c(bit): %s SCL unexpected low while pulling SDA low!\n",
|
||||
adap->name);
|
||||
goto bailout;
|
||||
}
|
||||
sdahi(adap);
|
||||
printk("i2c(bit):2 scl: %d sda: %d \n",getscl(adap),getsda(adap));
|
||||
if ( 0 == getsda(adap) ) {
|
||||
printk("i2c(bit): %s SDA stuck low!\n",adap->name);
|
||||
sdahi(adap);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == getscl(adap) ) {
|
||||
printk("i2c(bit): %s SCL unexpected low while SDA high!\n",adap->name);
|
||||
goto bailout;
|
||||
}
|
||||
scllo(adap);
|
||||
printk("i2c(bit):3 scl: %d sda: %d \n",getscl(adap),getsda(adap));
|
||||
if ( 0 != getscl(adap) ) {
|
||||
printk("i2c(bit): %s SCL stuck high!\n",adap->name);
|
||||
sclhi(adap);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == getsda(adap) ) {
|
||||
printk("i2c(bit): %s SDA unexpected low while pulling SCL low!\n",
|
||||
adap->name);
|
||||
goto bailout;
|
||||
}
|
||||
sclhi(adap);
|
||||
printk("i2c(bit):4 scl: %d sda: %d \n",getscl(adap),getsda(adap));
|
||||
if ( 0 == getscl(adap) ) {
|
||||
printk("i2c(bit): %s SCL stuck low!\n",adap->name);
|
||||
sclhi(adap);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == getsda(adap) ) {
|
||||
printk("i2c(bit): %s SDA unexpected low while SCL high!\n",
|
||||
adap->name);
|
||||
goto bailout;
|
||||
}
|
||||
printk("i2c(bit): %s passed test.\n",adap->name);
|
||||
return 0;
|
||||
bailout:
|
||||
sdahi(adap);
|
||||
sclhi(adap);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* ----- Utility functions
|
||||
*/
|
||||
|
||||
inline int try_address(struct bit_adapter *adap,
|
||||
unsigned char addr, int retries)
|
||||
{
|
||||
int i,ret = -1;
|
||||
for (i=0;i<retries;i++) {
|
||||
ret = i2c_outb(adap,addr);
|
||||
if (ret==1)
|
||||
break; /* success! */
|
||||
i2c_stop(adap);
|
||||
udelay(5/*adap->udelay*/);
|
||||
i2c_start(adap);
|
||||
udelay(adap->udelay);
|
||||
}
|
||||
DEB2(if (i) printk("i2c(bit): needed %d retries for %d\n",i,addr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sendbytes(struct bit_adapter *adap,const char *buf, int count)
|
||||
{
|
||||
char c;
|
||||
const char *temp = buf;
|
||||
int retval;
|
||||
int wrcount=0;
|
||||
|
||||
while (count > 0) {
|
||||
c = *temp;
|
||||
DEB2(printk("i2c(bit): %s i2c_write: writing %2.2X\n",
|
||||
adap->name, c&0xff));
|
||||
retval = i2c_outb(adap,c);
|
||||
if (retval>0) {
|
||||
count--;
|
||||
temp++;
|
||||
wrcount++;
|
||||
} else { /* arbitration or no acknowledge */
|
||||
printk("i2c(bit): %s i2c_write: error - bailout.\n",
|
||||
adap->name);
|
||||
i2c_stop(adap);
|
||||
return -EREMOTEIO; /* got a better one ?? */
|
||||
}
|
||||
#if 0
|
||||
/* from asm/delay.h */
|
||||
__delay(adap->mdelay * (loops_per_sec / 1000) );
|
||||
#endif
|
||||
}
|
||||
return wrcount;
|
||||
}
|
||||
|
||||
inline int readbytes(struct bit_adapter *adap,char *buf,int count)
|
||||
{
|
||||
char *temp = buf;
|
||||
int inval;
|
||||
int rdcount=0; /* counts bytes read */
|
||||
|
||||
while (count > 0) {
|
||||
inval = i2c_inb(adap);
|
||||
/*printk("%#02x ",inval);
|
||||
if ( ! (count % 16) )
|
||||
printk("\n");
|
||||
*/
|
||||
if (inval>=0) {
|
||||
*temp = inval;
|
||||
rdcount++;
|
||||
} else { /* read timed out */
|
||||
printk("i2c(bit): i2c_read: i2c_inb timed out.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( count > 1 ) { /* send ack */
|
||||
sdalo(adap);
|
||||
DEBPROTO(printk(" Am "));
|
||||
} else {
|
||||
sdahi(adap); /* neg. ack on last byte */
|
||||
DEBPROTO(printk(" NAm "));
|
||||
}
|
||||
if (sclhi(adap)<0) { /* timeout */
|
||||
sdahi(adap);
|
||||
printk("i2c(bit): i2c_read: Timeout at ack\n");
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
scllo(adap);
|
||||
sdahi(adap);
|
||||
temp++;
|
||||
count--;
|
||||
}
|
||||
return rdcount;
|
||||
}
|
||||
|
||||
inline int bit_doAddress(struct bit_adapter *adap, struct i2c_msg *msg,
|
||||
int retries)
|
||||
{
|
||||
unsigned short flags = msg->flags;
|
||||
unsigned char addr;
|
||||
int ret;
|
||||
if ( (flags & I2C_M_TEN) ) {
|
||||
/* a ten bit address */
|
||||
addr = 0xf0 | ( flags & I2C_M_TENMASK );
|
||||
DEB2(printk("addr0: %d\n",addr));
|
||||
/* try extended address code...*/
|
||||
ret = try_address(adap, addr, retries);
|
||||
if (ret!=1) {
|
||||
printk("died at extended address code.\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
/* the remaining 8 bit address */
|
||||
ret = i2c_outb(adap,msg->addr);
|
||||
if (ret != 1) {
|
||||
printk("died at 2nd address code.\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
if ( flags & I2C_M_RD ) {
|
||||
i2c_repstart(adap);
|
||||
/* okay, now switch into reading mode */
|
||||
addr |= 0x01;
|
||||
ret = try_address(adap, addr, retries);
|
||||
if (ret!=1) {
|
||||
printk("died at extended address code.\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
}
|
||||
} else { /* normal 7bit address */
|
||||
addr = ( msg->addr << 1 );
|
||||
if (flags & I2C_M_RD )
|
||||
addr |= 1;
|
||||
ret = try_address(adap, addr, retries);
|
||||
if (ret!=1) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bit_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct bit_adapter *adap = (struct bit_adapter*)adapter->data;
|
||||
struct i2c_msg *pmsg;
|
||||
int i,ret;
|
||||
|
||||
i2c_start(adap);
|
||||
for (i=0;i<num;i++) {
|
||||
pmsg = &msgs[i];
|
||||
ret = bit_doAddress(adap,pmsg,adapter->retries);
|
||||
if (ret != 0) {
|
||||
DEB2(printk("i2c(bit): NAK from device adr %#2x msg #%d\n"
|
||||
,msgs[i].addr,i));
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
if (pmsg->flags & I2C_M_RD ) {
|
||||
/* read bytes into buffer*/
|
||||
ret = readbytes(adap,pmsg->buf,pmsg->len);
|
||||
DEB2(printk("i2c(bit): read %d bytes.\n",ret));
|
||||
} else {
|
||||
/* write bytes from buffer */
|
||||
ret = sendbytes(adap,pmsg->buf,pmsg->len);
|
||||
DEB2(printk("i2c(bit): wrote %d bytes.\n",ret));
|
||||
}
|
||||
if (i<num-1) {
|
||||
i2c_repstart(adap);
|
||||
}
|
||||
}
|
||||
i2c_stop(adap);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
int algo_control(struct i2c_adapter *adapter,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_register(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct bit_adapter *adap = (struct bit_adapter*)adapter->data;
|
||||
|
||||
if (adap->client_register != NULL)
|
||||
return adap->client_register(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_unregister(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct bit_adapter *adap = (struct bit_adapter*)adapter->data;
|
||||
|
||||
if (adap->client_unregister != NULL)
|
||||
return adap->client_unregister(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
struct i2c_algorithm bit_algo = {
|
||||
"Bit-shift algorithm",
|
||||
ALGO_BIT,
|
||||
bit_xfer,
|
||||
#if 0
|
||||
bit_send, /* master_xmit */
|
||||
bit_recv, /* master_recv */
|
||||
bit_comb, /* master_comb */
|
||||
#endif
|
||||
NULL, /* slave_xmit */
|
||||
NULL, /* slave_recv */
|
||||
algo_control, /* ioctl */
|
||||
client_register,
|
||||
client_unregister,
|
||||
};
|
||||
|
||||
/*
|
||||
* registering functions to load algorithms at runtime
|
||||
*/
|
||||
int i2c_bit_add_bus(struct bit_adapter *adap)
|
||||
{
|
||||
int i,ack;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
|
||||
for (i = 0; i < BIT_ADAP_MAX; i++)
|
||||
if (NULL == bit_adaps[i])
|
||||
break;
|
||||
if (BIT_ADAP_MAX == i)
|
||||
return -ENOMEM;
|
||||
|
||||
if (bit_test) {
|
||||
int ret = test_bus(adap);
|
||||
if (ret<0)
|
||||
return -ENODEV;
|
||||
}
|
||||
i2c_adap = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
|
||||
if (i2c_adap == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
bit_adaps[i] = adap;
|
||||
adap_count++;
|
||||
DEB2(printk("i2c(bit): hw routines for %s registered.\n",adap->name));
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
memset(i2c_adap,0,sizeof(struct i2c_adapter));
|
||||
strcpy(i2c_adap->name,adap->name);
|
||||
i2c_adap->id = bit_algo.id | adap->id;
|
||||
i2c_adap->algo = &bit_algo;
|
||||
i2c_adap->data = adap;
|
||||
i2c_adap->timeout = 100; /* default values, should */
|
||||
i2c_adap->retries = 3; /* be replaced by defines */
|
||||
i2c_adaps[i] = i2c_adap;
|
||||
|
||||
/* scan bus */
|
||||
if (bit_scan) {
|
||||
printk(KERN_INFO " i2c(bit): scanning bus %s.\n", adap->name);
|
||||
for (i = 0x00; i < 0xff; i+=2) {
|
||||
i2c_start(adap);
|
||||
ack = i2c_outb(adap,i);
|
||||
i2c_stop(adap);
|
||||
if (ack>0) {
|
||||
printk("(%02x)",i>>1);
|
||||
} else
|
||||
printk(".");
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
i2c_add_adapter(i2c_adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int i2c_bit_del_bus(struct bit_adapter *adap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BIT_ADAP_MAX; i++)
|
||||
if ( adap == bit_adaps[i])
|
||||
break;
|
||||
if ( BIT_ADAP_MAX == i) {
|
||||
printk(KERN_WARNING " i2c(bit): could not unregister bus: %s\n",
|
||||
adap->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
bit_adaps[i] = NULL;
|
||||
i2c_del_adapter(i2c_adaps[i]);
|
||||
kfree(i2c_adaps[i]);
|
||||
i2c_adaps[i] = NULL;
|
||||
adap_count--;
|
||||
DEB2(printk("i2c(bit): adapter unregistered: %s\n",adap->name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int algo_bit_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<BIT_ADAP_MAX;i++) {
|
||||
bit_adaps[i]=NULL;
|
||||
}
|
||||
adap_count=0;
|
||||
i2c_add_algorithm(&bit_algo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
|
||||
|
||||
MODULE_PARM(bit_test, "i");
|
||||
MODULE_PARM(bit_scan, "i");
|
||||
MODULE_PARM(i2c_debug,"i");
|
||||
|
||||
MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
|
||||
MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
|
||||
MODULE_PARM_DESC(i2c_debug,"debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
|
||||
|
||||
|
||||
#ifndef LM_SENSORS
|
||||
EXPORT_SYMBOL(i2c_bit_add_bus);
|
||||
EXPORT_SYMBOL(i2c_bit_del_bus);
|
||||
#endif
|
||||
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return algo_bit_init();
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_del_algorithm(&bit_algo);
|
||||
}
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
#ifndef ALGO_BIT_H
|
||||
#define ALGO_BIT_H 1
|
||||
|
||||
/* --- Defines for bit-adapters --------------------------------------- */
|
||||
#include "i2c.h"
|
||||
/*
|
||||
* This struct contains the hw-dependent functions of bit-style adapters to
|
||||
* manipulate the line states, and to init any hw-specific features. This is
|
||||
* only used if you have more than one hw-type of adapter running.
|
||||
*/
|
||||
struct bit_adapter {
|
||||
char name[32]; /* give it a nice name */
|
||||
unsigned int id; /* not used yet, maybe later */
|
||||
void *data; /* private data for lowlevel routines */
|
||||
void (*setsda) (void *data, int state);
|
||||
void (*setscl) (void *data, int state);
|
||||
int (*getsda) (void *data);
|
||||
int (*getscl) (void *data);
|
||||
|
||||
/* administrative calls */
|
||||
int (*client_register)(struct i2c_client *);
|
||||
int (*client_unregister)(struct i2c_client *);
|
||||
|
||||
/* local settings */
|
||||
int udelay;
|
||||
int mdelay;
|
||||
int timeout;
|
||||
|
||||
};
|
||||
|
||||
extern struct bit_adapter *bit_adaps[];
|
||||
|
||||
#define BIT_ADAP_MAX 16
|
||||
|
||||
int i2c_bit_add_bus(struct bit_adapter *);
|
||||
int i2c_bit_del_bus(struct bit_adapter *);
|
||||
|
||||
#endif /* ALGO_BIT_H */
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* bit-elv.c i2c-hw access for philips style parallel port adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: bit-elv.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
|
||||
/*
|
||||
* $Log: bit-elv.c,v $
|
||||
* Revision 1.1 1998/09/05 18:20:09 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.3 1998/01/20 10:01:29 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.2 1997/06/15 14:21:37 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/errno.h>
|
||||
#include "i2c.h"
|
||||
#include "i2c-priv.h"
|
||||
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
#define DEBINIT(x) x /* detection status messages */
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
#if (BITADAPS) == 1
|
||||
#define Local inline
|
||||
#define bit_elv_getscl getscl
|
||||
#define bit_elv_setscl setscl
|
||||
#define bit_elv_getsda getsda
|
||||
#define bit_elv_setsda setsda
|
||||
#define bit_elv_bit_init bit_init
|
||||
#define bit_elv_bit_exit bit_exit
|
||||
#else
|
||||
#define Local static
|
||||
#endif
|
||||
|
||||
#define portData(minor) ((char)((int)i2c_table[minor].minor_data))
|
||||
|
||||
Local void bit_elv_setscl(int minor, int state)
|
||||
{
|
||||
if (state) {
|
||||
portData(minor)&=0xfe;
|
||||
} else {
|
||||
portData(minor)|=1;
|
||||
}
|
||||
outb(portData(minor), DATA);
|
||||
}
|
||||
|
||||
Local void bit_elv_setsda(int minor, int state)
|
||||
{
|
||||
if (state) {
|
||||
portData(minor)&=0xfd;
|
||||
} else {
|
||||
portData(minor)|=2;
|
||||
}
|
||||
outb(portData(minor), DATA);
|
||||
}
|
||||
|
||||
Local int bit_elv_getscl(int minor)
|
||||
{
|
||||
return ( 0 == ( (inb_p(STAT)) & 0x08 ) );
|
||||
}
|
||||
|
||||
Local int bit_elv_getsda(int minor)
|
||||
{
|
||||
return ( 0 == ( (inb_p(STAT)) & 0x40 ) );
|
||||
}
|
||||
|
||||
Local int bit_elv_bit_init(int minor)
|
||||
{
|
||||
if (check_region(i2c_table[minor].base,
|
||||
(i2c_table[minor].base == 0x3bc)? 3 : 8) < 0 ) {
|
||||
return -ENODEV;
|
||||
} else {
|
||||
/* test for ELV adap. */
|
||||
if (inb(STAT) & 0x80) { /* BUSY should be high */
|
||||
DEBINIT(printk("i2c ELV: Busy was low.\n"));
|
||||
return -ENODEV;
|
||||
} else {
|
||||
outb(0x04,CTRL); /* SLCT auf low */
|
||||
udelay(40);
|
||||
if ( inb(STAT) && 0x10 ) {
|
||||
outb(0x0c,CTRL);
|
||||
DEBINIT(printk("i2c ELV: Select was high.\n"));
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
request_region(i2c_table[minor].base,
|
||||
(i2c_table[minor].base == 0x3bc)? 3 : 8,
|
||||
"i2c (ELV adapter)");
|
||||
portData(minor) = 0;
|
||||
outb(0,DATA);
|
||||
}
|
||||
DEBINIT(printk("i2c%d: scl: %d sda %d \n",minor,
|
||||
bit_elv_getscl(minor),bit_elv_getsda(minor)) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Local void bit_elv_bit_exit(int minor)
|
||||
{
|
||||
outb(0,DATA);
|
||||
outb(0x0c,CTRL);
|
||||
release_region( i2c_table[minor].base ,
|
||||
(i2c_table[minor].base == 0x3bc)? 3 : 8 );
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
#if (BITADAPS) > 1
|
||||
struct i2c_bit_opns bit_elv_ops = {
|
||||
bit_elv_setscl,
|
||||
bit_elv_setsda,
|
||||
bit_elv_getscl,
|
||||
bit_elv_getsda,
|
||||
bit_elv_bit_init,
|
||||
bit_elv_bit_exit
|
||||
};
|
||||
#endif
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* bit-lp.c i2c-hw access for philips style parallel port adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: bit-lp.c,v 1.6 1998/12/30 08:36:08 i2c Exp i2c $";
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/stddef.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "algo-bit.h"
|
||||
|
||||
#define DEFAULT_BASE 0x378
|
||||
int base=0;
|
||||
|
||||
/* Note: all we need to know is the base address of the parallel port, so
|
||||
* instead of having a dedicated struct to store this value, we store this
|
||||
* int in the pointer field (=bit_lp_ops.data) itself.
|
||||
*/
|
||||
|
||||
/* Note2: as the hw that implements the i2c bus on the parallel port is
|
||||
* incompatible with other epp stuff etc., we access the port exclusively
|
||||
* and don't cooperate with parport functions.
|
||||
*/
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
|
||||
/* ----- printer port defines ------------------------------------------*/
|
||||
/* Pin Port Inverted name */
|
||||
#define I2C_ON 0x20 /* 12 status N paper */
|
||||
/* ... only for phil. not used */
|
||||
#define I2C_SDA 0x80 /* 9 data N data7 */
|
||||
#define I2C_SCL 0x08 /* 17 ctrl N dsel */
|
||||
|
||||
#define I2C_SDAIN 0x80 /* 11 stat Y busy */
|
||||
#define I2C_SCLIN 0x08 /* 15 stat Y enable */
|
||||
|
||||
#define I2C_DMASK 0x7f
|
||||
#define I2C_CMASK 0xf7
|
||||
|
||||
/* --- Convenience defines for the parallel port: */
|
||||
#define BASE (unsigned int)(data)
|
||||
#define DATA BASE /* Centronics data port */
|
||||
#define STAT (BASE+1) /* Centronics status port */
|
||||
#define CTRL (BASE+2) /* Centronics control port */
|
||||
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
|
||||
void bit_lp_setscl(void *data, int state)
|
||||
{
|
||||
/*be cautious about state of the control register -
|
||||
touch only the one bit needed*/
|
||||
if (state) {
|
||||
outb(inb(CTRL)|I2C_SCL, CTRL);
|
||||
} else {
|
||||
outb(inb(CTRL)&I2C_CMASK, CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lp_setsda(void *data, int state)
|
||||
{
|
||||
if (state) {
|
||||
outb(I2C_DMASK , DATA);
|
||||
} else {
|
||||
outb(I2C_SDA , DATA);
|
||||
}
|
||||
}
|
||||
|
||||
int bit_lp_getscl(void *data)
|
||||
{
|
||||
return ( 0 != ( (inb(STAT)) & I2C_SCLIN ) );
|
||||
}
|
||||
|
||||
int bit_lp_getsda(void *data)
|
||||
{
|
||||
return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) );
|
||||
}
|
||||
|
||||
int bit_lp_init(void)
|
||||
{
|
||||
if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
|
||||
return -ENODEV;
|
||||
} else {
|
||||
request_region(base,(base == 0x3bc)? 3 : 8,
|
||||
"i2c (parallel port adapter)");
|
||||
/* reset hardware to sane state */
|
||||
bit_lp_setsda((void*)base,1);
|
||||
bit_lp_setscl((void*)base,1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bit_lp_exit(void)
|
||||
{
|
||||
release_region( base , (base == 0x3bc)? 3 : 8 );
|
||||
}
|
||||
|
||||
int bit_lp_reg(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bit_lp_unreg(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
struct bit_adapter bit_lp_ops = {
|
||||
"Philips Parallel port adapter",
|
||||
HW_B_LP,
|
||||
NULL,
|
||||
bit_lp_setsda,
|
||||
bit_lp_setscl,
|
||||
bit_lp_getsda,
|
||||
bit_lp_getscl,
|
||||
bit_lp_reg,
|
||||
bit_lp_unreg,
|
||||
80, 80, 100, /* waits, timeout */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter");
|
||||
|
||||
MODULE_PARM(base, "i");
|
||||
|
||||
#ifndef LM_SENSORS
|
||||
EXPORT_NO_SYMBOLS;
|
||||
#endif
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
if (base==0) {
|
||||
/* probe some values */
|
||||
base=DEFAULT_BASE;
|
||||
bit_lp_ops.data=(void*)DEFAULT_BASE;
|
||||
if (bit_lp_init()==0) {
|
||||
i2c_bit_add_bus(&bit_lp_ops);
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
bit_lp_ops.data=(void*)base;
|
||||
if (bit_lp_init()==0) {
|
||||
i2c_bit_add_bus(&bit_lp_ops);
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
printk("bit_lp: found device at %#x.\n",base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_bit_del_bus(&bit_lp_ops);
|
||||
bit_lp_exit();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
-196
@@ -1,196 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* bit-velle.c i2c-hw access for Velleman K9000 adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-96 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: bit-velle.c,v 1.4 1998/12/30 08:36:08 i2c Exp i2c $";
|
||||
/*
|
||||
* $Log: bit-velle.c,v $
|
||||
* Revision 1.4 1998/12/30 08:36:08 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.3 1998/09/15 18:50:04 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.2 1998/09/13 16:54:55 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.1 1998/07/29 08:09:35 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.1 1998/01/20 10:01:29 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.1 1996/11/17 11:00:03 i2c
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h> /* for 2.0 kernels to get NULL */
|
||||
#include <asm/errno.h> /* for 2.0 kernels to get ENODEV */
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "algo-bit.h"
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
|
||||
/* Pin Port Inverted name */
|
||||
#define I2C_SDA 0x02 /* ctrl bit 1 (inv) */
|
||||
#define I2C_SCL 0x08 /* ctrl bit 3 (inv) */
|
||||
|
||||
#define I2C_SDAIN 0x10 /* stat bit 4 */
|
||||
#define I2C_SCLIN 0x08 /* ctrl bit 3 (inv) (reads own output) */
|
||||
|
||||
#define I2C_DMASK 0xfd
|
||||
#define I2C_CMASK 0xf7
|
||||
|
||||
|
||||
/* --- Convenience defines for the parallel port: */
|
||||
#define BASE (unsigned int)(data)
|
||||
#define DATA BASE /* Centronics data port */
|
||||
#define STAT (BASE+1) /* Centronics status port */
|
||||
#define CTRL (BASE+2) /* Centronics control port */
|
||||
|
||||
#define DEFAULT_BASE 0x378
|
||||
int base=0;
|
||||
|
||||
/* ----- local functions --------------------------------------------------- */
|
||||
|
||||
void bit_velle_setscl(void *data, int state)
|
||||
{
|
||||
if (state) {
|
||||
outb(inb(CTRL) & I2C_CMASK, CTRL);
|
||||
} else {
|
||||
outb(inb(CTRL) | I2C_SCL, CTRL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void bit_velle_setsda(void *data, int state)
|
||||
{
|
||||
if (state) {
|
||||
outb(inb(CTRL) & I2C_DMASK , CTRL);
|
||||
} else {
|
||||
outb(inb(CTRL) | I2C_SDA, CTRL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int bit_velle_getscl(void *data)
|
||||
{
|
||||
return ( 0 == ( (inb(CTRL)) & I2C_SCLIN ) );
|
||||
}
|
||||
|
||||
int bit_velle_getsda(void *data)
|
||||
{
|
||||
return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) );
|
||||
}
|
||||
|
||||
int bit_velle_init(void)
|
||||
{
|
||||
if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
|
||||
DEBE(printk("i2c_init: Port %#x already in use.\n", base));
|
||||
return -ENODEV;
|
||||
} else {
|
||||
request_region(base, (base == 0x3bc)? 3 : 8,
|
||||
"i2c (Vellemann adapter)");
|
||||
bit_velle_setsda((void*)base,1);
|
||||
bit_velle_setscl((void*)base,1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bit_velle_exit(void)
|
||||
{
|
||||
release_region( base , (base == 0x3bc)? 3 : 8 );
|
||||
}
|
||||
|
||||
|
||||
int bit_velle_reg(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bit_velle_unreg(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
struct bit_adapter bit_velle_ops = {
|
||||
"Philips Parallel port adapter",
|
||||
HW_B_LP,
|
||||
NULL,
|
||||
bit_velle_setsda,
|
||||
bit_velle_setscl,
|
||||
bit_velle_getsda,
|
||||
bit_velle_getscl,
|
||||
bit_velle_reg,
|
||||
bit_velle_unreg,
|
||||
10, 10, 100, /* waits, timeout */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K9000 adapter");
|
||||
|
||||
MODULE_PARM(base, "i");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
if (base==0) {
|
||||
/* probe some values */
|
||||
base=DEFAULT_BASE;
|
||||
bit_velle_ops.data=(void*)DEFAULT_BASE;
|
||||
if (bit_velle_init()==0) {
|
||||
i2c_bit_add_bus(&bit_velle_ops);
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
bit_velle_ops.data=(void*)base;
|
||||
if (bit_velle_init()==0) {
|
||||
i2c_bit_add_bus(&bit_velle_ops);
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
printk("bit_velle: found device at %#x.\n",base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_bit_del_bus(&bit_velle_ops);
|
||||
bit_velle_exit();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# $Id: Makefile,v 1.1 1996/12/04 20:40:10 i2c Exp $
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.1 1996/12/04 20:40:10 i2c
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
I2C_HOME = ..
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
I2C_OPT = -DVERIFY_HEADERS -DSLOW_STARTER
|
||||
KERNEL_OPT = -D__KERNEL__ -DKERNEL -DLINUX -DMODULE
|
||||
WARNINGS = -Wall -Wstrict-prototypes
|
||||
COMPILE = -pipe -fomit-frame-pointer -m486 -O2 \
|
||||
-I$(I2C_HOME) -I.
|
||||
DEBUG =
|
||||
|
||||
SRCS = i2c_main.c alg-illeg.c $(HW_SRCS)
|
||||
INCLUDES = i2c_priv.h
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
HDRS = i2c_priv.h
|
||||
MOD = i2c
|
||||
|
||||
CFLAGS = $(DEBUG) $(WARNINGS) $(COMPILE) $(I2C_OPT) $(KERNEL_OPT)
|
||||
SFLAGS = -fverbose-asm $(WARNINGS) $(COMPILE) $(PRT_OPT) $(KERNEL_OPT)
|
||||
|
||||
all: detect
|
||||
|
||||
clean:
|
||||
-rm -f detect
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# Module.mk - Makefile for a Linux module for reading sensor data.
|
||||
# Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Note that MODULE_DIR (the directory in which this file resides) is a
|
||||
# 'simply expanded variable'. That means that its value is substituted
|
||||
# verbatim in the rules, until it is redefined.
|
||||
MODULE_DIR := i2c/detect
|
||||
|
||||
# Regrettably, even 'simply expanded variables' will not put their currently
|
||||
# defined value verbatim into the command-list of rules...
|
||||
I2CDETECTTARGETS := $(MODULE_DIR)/detect
|
||||
I2CDETECTSOURCES := $(MODULE_DIR)/detect.c
|
||||
|
||||
# Include all dependency files
|
||||
INCLUDEFILES += $(I2CDETECTSOURCES:.c=.rd)
|
||||
|
||||
all-i2c-detect: $(I2CDETECTTARGETS)
|
||||
all :: all-i2c-detect
|
||||
|
||||
# No install rule
|
||||
|
||||
clean-i2c-detect:
|
||||
$(RM) $(I2CDETECTSOURCES:.c=.rd) $(I2CDETECTSOURCES:.c=.ro) \
|
||||
$(I2CDETECTTARGETS)
|
||||
clean :: clean-i2c-detect
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* detect -- look who's there. Gets address acks from all devices on the bus.*/
|
||||
/* It should not change any values in the peripherals. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char *rcsid="$Id: detect.c,v 2.2 1996/11/17 22:03:06 i2c Exp $";
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include "i2c.h"
|
||||
|
||||
#define Write(a,b,c) err(1,write(a,b,c))
|
||||
#define Read(a,b,c) err(0,read(a,b,c))
|
||||
|
||||
void err(int wr, int d){
|
||||
if (d==-1){
|
||||
printf("%s error: %s !\n",(wr)?"Write":"Read",strerror(errno));
|
||||
}
|
||||
}
|
||||
#define ERR(x) printf("return value: %d\n", (x) );
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int i,f;
|
||||
char b[40],c;
|
||||
char *device = "/dev/i2c0";
|
||||
|
||||
/* parse options */
|
||||
opterr=1;
|
||||
while ( (c=getopt(argc,argv,"hH?d:")) != -1) {
|
||||
switch (c){
|
||||
case 'd':
|
||||
if (optarg)
|
||||
device = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
case '?':
|
||||
default:
|
||||
printf("%s tries to detect devices on the i2c-bus. Usage:\n",argv[0]);
|
||||
printf("-d device device to use\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
f=open(device,O_RDWR);
|
||||
if (f<0){
|
||||
perror("detect");
|
||||
exit(1);
|
||||
}
|
||||
ERR( ioctl(f,I2C_UDELAY,10) );
|
||||
ERR( ioctl(f,I2C_MDELAY,0) );
|
||||
// ERR( ioctl(f,I2C_RETRIES,3) );
|
||||
|
||||
for (i=0;i<128;i++){
|
||||
ioctl(f,I2C_SLAVE,i);
|
||||
if (0>read (f,b,0) ) {
|
||||
putchar('.');
|
||||
} else {
|
||||
printf("\n%d worked! \n",i);
|
||||
}
|
||||
usleep(100);
|
||||
fflush(stdout);
|
||||
}
|
||||
putchar('\n');
|
||||
return close(f);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#################################################
|
||||
# config
|
||||
KERNEL_LOCATION=/usr/src/linux
|
||||
CURRENT=$(shell uname -r)
|
||||
|
||||
#################################################
|
||||
# some magic for using linux kernel settings
|
||||
# when compiling module(s)
|
||||
|
||||
M_OBJS = eeprom.o hw-monitor.c
|
||||
MX_OBJS =
|
||||
EXTRA_CFLAGS = -DVERIFY_HEADERS -DSLOW_STARTER -I..
|
||||
|
||||
here:
|
||||
DIR=`pwd`; (cd $(KERNEL_LOCATION); make SUBDIRS=$$DIR modules)
|
||||
|
||||
install:
|
||||
su -c "cp -v $(M_OBJS) $(MX_OBJS) /lib/modules/$(CURRENT)/misc"
|
||||
|
||||
clean:
|
||||
-rm -f $(M_OBJS) $(MX_OBJS) .*.o.flags *~
|
||||
|
||||
include $(KERNEL_LOCATION)/Rules.make
|
||||
@@ -1,37 +0,0 @@
|
||||
# Module.mk - Makefile for a Linux module for reading sensor data.
|
||||
# Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Note that MODULE_DIR (the directory in which this file resides) is a
|
||||
# 'simply expanded variable'. That means that its value is substituted
|
||||
# verbatim in the rules, until it is redefined.
|
||||
MODULE_DIR := i2c/drivers
|
||||
|
||||
# Regrettably, even 'simply expanded variables' will not put their currently
|
||||
# defined value verbatim into the command-list of rules...
|
||||
I2CDRIVERTARGETS := $(MODULE_DIR)/eeprom.o
|
||||
|
||||
# Include all dependency files
|
||||
INCLUDEFILES += $(I2CDRIVERTARGETS:.o=.d)
|
||||
|
||||
all-i2c-drivers: $(I2CDRIVERTARGETS)
|
||||
all :: all-i2c-drivers
|
||||
|
||||
# No install rule: Our own eeprom.o driver is better :-)
|
||||
|
||||
clean-i2c-drivers:
|
||||
$(RM) $(I2CDRIVERTARGETS) $(I2CDRIVERTARGETS:.o=.d)
|
||||
clean :: clean-i2c-drivers
|
||||
@@ -1,172 +0,0 @@
|
||||
/* experimental eeprom driver
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/malloc.h>
|
||||
|
||||
#include "i2c.h" /* +++ simon */
|
||||
#include "algo-bit.h"
|
||||
|
||||
|
||||
int test=0;
|
||||
/*
|
||||
* Read the configuration EEPROM
|
||||
*/
|
||||
#define EEPROM_ADDR 0x50
|
||||
|
||||
#define EEPROM_FROM 0x50
|
||||
#define EEPROM_TO 0x58 /*exclusive.*/
|
||||
|
||||
#define MEMSIZE 128 /* default eeprom memory size */
|
||||
/* i2c_client identifies a single device that is connected to an
|
||||
* i2c bus.
|
||||
*/
|
||||
struct i2c_driver eepromDriver;
|
||||
|
||||
struct {
|
||||
int size; /* eeprom memory size*/
|
||||
unsigned int flags;
|
||||
unsigned char *memory;
|
||||
} eepromData;
|
||||
|
||||
struct i2c_client eepromTmpl = {
|
||||
"Winnov EEPROM",
|
||||
0,
|
||||
0,
|
||||
EEPROM_ADDR,
|
||||
NULL, /* the adapter we sit on */
|
||||
&eepromDriver, /* and our access routines */
|
||||
NULL, /* for the clients */
|
||||
};
|
||||
|
||||
|
||||
int eeprom_attach(struct i2c_adapter *adap)
|
||||
{
|
||||
struct i2c_client *eeprom;
|
||||
unsigned char buf[256];
|
||||
struct i2c_msg msgs[] = {
|
||||
{EEPROM_ADDR, 0, 1, "\0", },
|
||||
{EEPROM_ADDR, I2C_M_RD, 256, buf, },
|
||||
};
|
||||
__u8 c=0;
|
||||
int i;
|
||||
int ret=0;
|
||||
|
||||
printk("wnv-eeprom: Trying to attach to adapter %s \n",adap->name);
|
||||
printk("Looking for EEPROMs\n");
|
||||
eepromTmpl.adapter = adap;
|
||||
for (i=EEPROM_FROM;i<EEPROM_TO;i++) {
|
||||
/* we misuse the template as a "generic" eeprom client...*/
|
||||
eepromTmpl.addr = i;
|
||||
ret = i2c_master_send(&eepromTmpl,(unsigned char*)&c,1);
|
||||
if (ret!=1) {
|
||||
/* no device at this address. */
|
||||
/* printk("eeprom: failed for %x (%d)\n",i,ret);*/
|
||||
continue;
|
||||
}
|
||||
printk("eeprom: success with %x\n",i);
|
||||
if (test) {
|
||||
msgs[0].addr = i;
|
||||
msgs[1].addr = i;
|
||||
ret = i2c_transfer(adap, msgs, 2);
|
||||
if (ret != 2 ) {
|
||||
printk("eeprom: test read error with %d!\n",
|
||||
i);
|
||||
} else {
|
||||
int j;
|
||||
for (j=0;j<256;j+=8)
|
||||
printk("%2d: %#02x %#02x %#02x %#02x - %#02x %#02x %#02x %#02x \n",
|
||||
j,buf[j+0],buf[j+1],buf[j+2],buf[j+3],
|
||||
buf[j+4],buf[j+5],buf[j+6],buf[j+7]);
|
||||
}
|
||||
}
|
||||
eeprom = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (eeprom == NULL)
|
||||
return 0;
|
||||
memcpy(eeprom, &eepromTmpl, sizeof(struct i2c_client));
|
||||
i2c_attach_client(eeprom);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eeprom_detach(struct i2c_client *client)
|
||||
{
|
||||
printk("wnv-eeprom: Client %s wants to detach\n",client->name);
|
||||
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LOAD_EEPROM 1
|
||||
#if 0
|
||||
#define SET_SIZE 0xee01 /* set memory size */
|
||||
#define GET_SIZE 0xee02 /* get memory size */
|
||||
#define GET_MEM 0xee03 /* load data from eeprom & pass memory pointer */
|
||||
#define SET_MEM 0xee04 /* dump memory to eeprom */
|
||||
#define OPT
|
||||
#endif
|
||||
int eeprom_command(struct i2c_client *client,unsigned int cmd, void *arg)
|
||||
{
|
||||
switch(cmd) {
|
||||
case LOAD_EEPROM: {
|
||||
#if 0
|
||||
__u8 c=0;
|
||||
int i, ret,d;
|
||||
i2c_master_send(client,(unsigned char*)&c,1);
|
||||
i2c_master_recv(client, (char*)&c,1);
|
||||
i2c_master_send(client,(unsigned char*)&c,1);
|
||||
ret = i2c_master_recv(client, (char*)& ,
|
||||
sizeof(struct EEPROM));
|
||||
if (ret != sizeof(struct EEPROM)) {
|
||||
err_msg("wnv-eeprom: could only read %d bytes!\n"
|
||||
,ret);
|
||||
return -1;
|
||||
}
|
||||
for (d=0,i=0;i<sizeof(struct EEPROM); i++) {
|
||||
d+=((char *)(&dev->eeprom))[i];
|
||||
}
|
||||
if ((__u8)d != 0xff) {
|
||||
err_msg("wnv-eeprom: Checksum error in configuration EEPROM\n");
|
||||
return -1;
|
||||
}
|
||||
info_msg("wnv-eeprom: Identified: %s\n", dev->eeprom.szProduct);
|
||||
#endif
|
||||
} break;
|
||||
default:
|
||||
printk("eeprom: unknown command %x!\n",cmd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct i2c_driver eepromDriver = {
|
||||
"Videum EEPROM",
|
||||
-1,
|
||||
DF_NOTIFY,
|
||||
eeprom_attach,
|
||||
eeprom_detach,
|
||||
eeprom_command,
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_PARM(test,"i");
|
||||
|
||||
/*EXPORT_NO_SYMBOLS;*/
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
/* register drivers to the i2c bus admin. system.
|
||||
* These get notified upon attachment of adapters &
|
||||
* in turn create new clients that are connected to
|
||||
* these adapters...
|
||||
*/
|
||||
i2c_add_driver(&eepromDriver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_del_driver(&eepromDriver);
|
||||
}
|
||||
#endif /* MODULE*/
|
||||
@@ -1,41 +0,0 @@
|
||||
# $Id: Makefile,v 1.1 1996/07/23 20:31:56 i2c Exp $
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.1 1996/07/23 20:31:56 i2c
|
||||
# Initial revision
|
||||
#
|
||||
|
||||
I2C_HOME = ..
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
I2C_OPT = -DVERIFY_HEADERS -DSLOW_STARTER
|
||||
WARNINGS = -Wall -Wstrict-prototypes
|
||||
COMPILE = -pipe -fomit-frame-pointer -m486 -O2 \
|
||||
-I$(I2C_HOME) -I.
|
||||
DEBUG =
|
||||
|
||||
SRCS = i2c_main.c adap-illeg.c adap-phil.c adap-lppcf.c adap-isapcf.c \
|
||||
# adap-lpbit.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
HDRS = i2c_priv.h
|
||||
MAIN = eeprom
|
||||
|
||||
CFLAGS = $(DEBUG) $(WARNINGS) $(COMPILE) $(I2C_OPT) $(KERNEL_OPT)
|
||||
SFLAGS = -fverbose-asm $(WARNINGS) $(COMPILE) $(PRT_OPT) $(KERNEL_OPT)
|
||||
|
||||
all: $(MAIN)
|
||||
|
||||
install: $(MAIN)
|
||||
-@mkdir $(I2C_HOME)/bin
|
||||
cp $(MAIN) $(I2C_HOME)/bin
|
||||
|
||||
clean:
|
||||
-rm -f a.out $(OBJS) $(MAIN) core .depend detect
|
||||
|
||||
dep depend .depend: $(HDRS) $(SRCS)
|
||||
gcc $(CFLAGS) $(SRCS) -M >.depend
|
||||
#
|
||||
# include dependency files if they exist
|
||||
#
|
||||
#ifeq (.depend,$(wildcard .depend))
|
||||
#include .depend
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
# Module.mk - Makefile for a Linux module for reading sensor data.
|
||||
# Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Note that MODULE_DIR (the directory in which this file resides) is a
|
||||
# 'simply expanded variable'. That means that its value is substituted
|
||||
# verbatim in the rules, until it is redefined.
|
||||
MODULE_DIR := i2c/eeprom
|
||||
|
||||
# Regrettably, even 'simply expanded variables' will not put their currently
|
||||
# defined value verbatim into the command-list of rules...
|
||||
I2CEEPROMTARGETS := $(MODULE_DIR)/eeprom
|
||||
I2CEEPROMSOURCES := $(MODULE_DIR)/eeprom.c
|
||||
|
||||
# Include all dependency files. We use '.rd' to indicate this will create
|
||||
# executables.
|
||||
INCLUDEFILES += $(I2CEEPROMSOURCES:.c=.rd)
|
||||
|
||||
all-i2c-eeprom: $(I2CEEPROMTARGETS)
|
||||
all :: all-i2c-eeprom
|
||||
|
||||
# No install rule
|
||||
|
||||
clean-i2c-eeprom:
|
||||
$(RM) $(I2CEEPROMSOURCES:.c=.rd) $(I2CEEPROMSOURCES:.c=.ro) \
|
||||
$(I2CEEPROMTARGETS)
|
||||
clean :: clean-i2c-eeprom
|
||||
@@ -1,4 +0,0 @@
|
||||
This is a simple demo program that prints out the
|
||||
first 256 bytes of an EEPROM memory. Adittionally,
|
||||
you can write a test pattern to the chip.
|
||||
With -[aA] the chip address may be specified.
|
||||
@@ -1,16 +0,0 @@
|
||||
0000 bd 06 04 00 00 00 00 00 00 00 00 00 07 00 00 00 ................
|
||||
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
0020 00 00 00 00 00 00 00 00 00 30 36 00 00 00 00 00 .........06.....
|
||||
0030 00 00 00 00 00 00 00 00 00 56 69 64 65 75 6d 41 .........VideumA
|
||||
0040 56 20 2d 20 50 6c 75 67 20 61 6e 64 20 50 6c 61 V...Plug.and.Pla
|
||||
0050 79 00 00 00 00 00 00 57 69 6e 6e 6f 76 00 00 00 y......Winnov...
|
||||
0060 00 00 00 00 00 00 00 00 00 00 00 34 35 58 45 37 ...........45XE7
|
||||
0070 33 30 30 34 38 30 32 30 00 00 00 00 00 00 00 6d 30048020.......m
|
||||
0080 bd 06 04 00 00 00 00 00 00 00 00 00 07 00 00 00 ................
|
||||
0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
00a0 00 00 00 00 00 00 00 00 00 30 36 00 00 00 00 00 .........06.....
|
||||
00b0 00 00 00 00 00 00 00 00 00 56 69 64 65 75 6d 41 .........VideumA
|
||||
00c0 56 20 2d 20 50 6c 75 67 20 61 6e 64 20 50 6c 61 V...Plug.and.Pla
|
||||
00d0 79 00 00 00 00 00 00 57 69 6e 6e 6f 76 00 00 00 y......Winnov...
|
||||
00e0 00 00 00 00 00 00 00 00 00 00 00 34 35 58 45 37 ...........45XE7
|
||||
00f0 33 30 30 34 38 30 32 30 00 00 00 00 00 00 00 6d 30048020.......m
|
||||
@@ -1,16 +0,0 @@
|
||||
0000 bd 06 04 00 00 00 00 00 00 00 00 00 07 00 00 00 ................
|
||||
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
0020 00 00 00 00 00 00 00 00 00 30 36 00 00 00 00 00 .........06.....
|
||||
0030 00 00 00 00 00 00 00 00 00 56 69 64 65 75 6d 41 .........VideumA
|
||||
0040 56 20 2d 20 50 6c 75 67 20 61 6e 64 20 50 6c 61 V...Plug.and.Pla
|
||||
0050 79 00 00 00 00 00 00 57 69 6e 6e 6f 76 00 00 00 y......Winnov...
|
||||
0060 00 00 00 00 00 00 00 00 00 00 00 34 35 58 45 37 ...........45XE7
|
||||
0070 33 30 30 34 38 30 32 30 00 00 00 00 00 00 00 6d 30048020.......m
|
||||
0080 bd 06 04 00 00 00 00 00 00 00 00 00 07 00 00 00 ................
|
||||
0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
00a0 00 00 00 00 00 00 00 00 00 30 36 00 00 00 00 00 .........06.....
|
||||
00b0 00 00 00 00 00 00 00 00 00 56 69 64 65 75 6d 41 .........VideumA
|
||||
00c0 56 20 2d 20 50 6c 75 67 20 61 6e 64 20 50 6c 61 V...Plug.and.Pla
|
||||
00d0 79 00 00 00 00 00 00 57 69 6e 6e 6f 76 00 00 00 y......Winnov...
|
||||
00e0 00 00 00 00 00 00 00 00 00 00 00 34 35 58 45 37 ...........45XE7
|
||||
00f0 33 30 30 34 38 30 32 30 00 00 00 00 00 00 00 6d 30048020.......m
|
||||
@@ -1,187 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* eeprom -- read eeprom contents */
|
||||
/* revamped by Gerd Knorr */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char *rcsid="$Id: eeprom.c,v 1.1 1996/07/23 20:32:12 i2c Exp $";
|
||||
/*
|
||||
* $Log: eeprom.c,v $
|
||||
* Revision 1.1 1996/07/23 20:32:12 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.2 1996/07/06 17:20:38 i2c
|
||||
* rewrote loop
|
||||
*
|
||||
* Revision 1.1 1996/03/15 08:55:53 root
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
char *dev="/dev/i2c0";
|
||||
int wr=0, adr=0xa0;
|
||||
|
||||
|
||||
|
||||
void usage(char *name)
|
||||
{
|
||||
fprintf(stderr,"This is a i2c EEPROM tool\n");
|
||||
fprintf(stderr," read data: %s [ options ] > file\n",name);
|
||||
fprintf(stderr," write data: %s [ options ] -w < file\n",name);
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"File format is a hex dump. Without \"-w\" switch\n");
|
||||
fprintf(stderr,"only parsing (and printing) of the data is done,\n");
|
||||
fprintf(stderr,"writing is skipped.\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"options:\n");
|
||||
fprintf(stderr," -d device device to use [%s]\n",dev);
|
||||
fprintf(stderr," -a addr set slave address [0x%02x]\n",adr);
|
||||
fprintf(stderr,"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void dump_buf(unsigned char *buf)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i = 0; i < 256; i += 16) {
|
||||
printf("%04x ",i);
|
||||
for (j = i; j < i+16; j++) {
|
||||
if (!(j%4))
|
||||
printf(" ");
|
||||
printf("%02x ",buf[j]);
|
||||
}
|
||||
printf(" ");
|
||||
for (j = i; j < i+16; j++)
|
||||
printf("%c",isalnum(buf[j]) ? buf[j] : '.');
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int parse_buf(unsigned char *buf)
|
||||
{
|
||||
int i,j,n,pos,count;
|
||||
char line[100];
|
||||
|
||||
for (i = 0; i < 256; i += 16) {
|
||||
if (NULL == fgets(line,99,stdin)) {
|
||||
fprintf(stderr,"unexpected EOF\n");
|
||||
return -1;
|
||||
}
|
||||
if (1 != sscanf(line,"%x%n",&n,&pos)) {
|
||||
fprintf(stderr,"addr parse error (%d)\n",i>>4);
|
||||
return -1;
|
||||
}
|
||||
if (n != i) {
|
||||
fprintf(stderr,"addr mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
for (j = i; j < i+16; j++) {
|
||||
if (1 != sscanf(line+pos,"%x%n",&n,&count)) {
|
||||
fprintf(stderr,"value parse error\n");
|
||||
return -1;
|
||||
}
|
||||
buf[j] = n;
|
||||
pos += count;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
read_buf(int fd, unsigned char *buf)
|
||||
{
|
||||
int i,n=8;
|
||||
unsigned char addr;
|
||||
|
||||
for (i = 0; i < 256; i += n) {
|
||||
addr = i;
|
||||
if (-1 == (write(fd,&addr,1))) {
|
||||
fprintf(stderr,"write addr %s: %s\n",dev,strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (-1 == (read(fd,buf+i,n))) {
|
||||
fprintf(stderr,"read data %s: %s\n",dev,strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
int
|
||||
write_buf(int fd, unsigned char *buf)
|
||||
{
|
||||
int i,j,n = 8;
|
||||
unsigned char tmp[17];
|
||||
|
||||
for (i = 0; i < 256; i += n) {
|
||||
tmp[0] = i;
|
||||
for (j = 0; j < n; j++)
|
||||
tmp[j+1] = buf[i+j];
|
||||
if (-1 == (write(fd,tmp,n+1))) {
|
||||
fprintf(stderr," write data %s: %s\n",dev,strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr,"*");
|
||||
usleep(100000); /* 0.1 sec */
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int f,c,rescue;
|
||||
unsigned char buf[256];
|
||||
|
||||
/* parse options */
|
||||
opterr=1;
|
||||
while ( (c=getopt(argc,argv,"hrwa:d:")) != -1) {
|
||||
switch (c){
|
||||
case 'r':
|
||||
rescue=1;
|
||||
break;
|
||||
case 'w':
|
||||
wr=1;
|
||||
break;
|
||||
case 'd':
|
||||
dev = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
adr = strtol(optarg,NULL,0);
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 == (f = open(dev,O_RDWR))) {
|
||||
fprintf(stderr,"open %s: %s\n",dev,strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
ioctl(f,I2C_SLAVE,adr>>1);
|
||||
memset(buf,0,256);
|
||||
|
||||
if (isatty(fileno(stdin))) {
|
||||
/* read */
|
||||
read_buf(f,buf);
|
||||
dump_buf(buf);
|
||||
} else {
|
||||
/* write */
|
||||
if (-1 == parse_buf(buf))
|
||||
exit(1);
|
||||
dump_buf(buf);
|
||||
if (wr) {
|
||||
fprintf(stderr,"writing to eeprom now... ");
|
||||
write_buf(f,buf);
|
||||
fprintf(stderr," ok\n");
|
||||
}
|
||||
}
|
||||
|
||||
close(f);
|
||||
exit(0);
|
||||
}
|
||||
-484
@@ -1,484 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* i2c.c - a device driver for the iic-bus interface */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-98 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define RCSID "$Id: i2c-core.c,v 1.1 1998/12/30 08:36:08 i2c Exp i2c $"
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/malloc.h>
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020301
|
||||
#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
|
||||
#endif
|
||||
|
||||
/* ----- global defines ---------------------------------------------------- */
|
||||
|
||||
/* exclusive access to the bus */
|
||||
/*#define I2C_SPINLOCK*/
|
||||
#ifdef I2C_SPINLOCK
|
||||
#define I2C_LOCK(adap) spin_lock_irqsave(&adap->lock,adap->lockflags)
|
||||
#define I2C_UNLOCK(adap) spin_unlock_irqrestore(&adap->lock,adap->lockflags)
|
||||
#else
|
||||
#define I2C_LOCK(adap) down(&adap->lock)
|
||||
#define I2C_UNLOCK(adap) up(&adap->lock)
|
||||
#endif
|
||||
|
||||
#define DEB(x) if (i2c_debug>=1) x;
|
||||
#define DEB2(x) if (i2c_debug>=2) x;
|
||||
|
||||
/* ----- global variables -------------------------------------------------- */
|
||||
|
||||
/**** algorithm list */
|
||||
struct i2c_algorithm *algorithms[I2C_ALGO_MAX];
|
||||
int algo_count;
|
||||
|
||||
/**** adapter list */
|
||||
struct i2c_adapter *adapters[I2C_ADAP_MAX];
|
||||
int adap_count;
|
||||
|
||||
/**** drivers list */
|
||||
struct i2c_driver *drivers[I2C_DRIVER_MAX];
|
||||
int driver_count;
|
||||
|
||||
/**** debug level */
|
||||
int i2c_debug=1;
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* registering functions
|
||||
* ---------------------------------------------------
|
||||
*/
|
||||
|
||||
/* -----
|
||||
* Algorithms - used to access groups of similar hw adapters or
|
||||
* specific interfaces like the PCF8584 et al.
|
||||
*/
|
||||
int i2c_add_algorithm(struct i2c_algorithm *algo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_ALGO_MAX; i++)
|
||||
if (NULL == algorithms[i])
|
||||
break;
|
||||
if (I2C_ALGO_MAX == i) {
|
||||
printk(KERN_WARNING
|
||||
" i2c: register_algorithm(%s) - enlarge I2C_ALGO_MAX.\n",
|
||||
algo->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
algorithms[i] = algo;
|
||||
algo_count++;
|
||||
|
||||
DEB(printk("i2c: algorithm %s registered.\n",algo->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int i2c_del_algorithm(struct i2c_algorithm *algo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_ALGO_MAX; i++)
|
||||
if (algo == algorithms[i])
|
||||
break;
|
||||
if (I2C_ALGO_MAX == i) {
|
||||
printk(KERN_WARNING
|
||||
" i2c: unregister_algorithm: [%s] not found.\n",
|
||||
algo->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
algorithms[i] = NULL;
|
||||
algo_count--;
|
||||
|
||||
DEB(printk("i2c: algorithm unregistered: %s\n",algo->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* -----
|
||||
* i2c_add_adapter is called from within the algorithm layer,
|
||||
* when a new hw adapter registers. A new device is register to be
|
||||
* available for clients.
|
||||
*/
|
||||
int i2c_add_adapter(struct i2c_adapter *adap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_ADAP_MAX; i++)
|
||||
if (NULL == adapters[i])
|
||||
break;
|
||||
if (I2C_ADAP_MAX == i) {
|
||||
printk(KERN_WARNING
|
||||
" i2c: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
|
||||
adap->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
adapters[i] = adap;
|
||||
adap_count++;
|
||||
|
||||
/* init data types */
|
||||
#ifdef I2C_SPINLOCK
|
||||
adap->lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
|
||||
#else
|
||||
init_MUTEX(&adap->lock);
|
||||
#endif
|
||||
|
||||
/* inform drivers of new adapters */
|
||||
for (i=0;i<I2C_DRIVER_MAX;i++)
|
||||
if (drivers[i]!=NULL && drivers[i]->flags&DF_NOTIFY)
|
||||
drivers[i]->attach_adapter(adap);
|
||||
|
||||
DEB(printk("i2c: adapter %s registered.\n",adap->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_del_adapter(struct i2c_adapter *adap)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i = 0; i < I2C_ADAP_MAX; i++)
|
||||
if (adap == adapters[i])
|
||||
break;
|
||||
if (I2C_ADAP_MAX == i) {
|
||||
printk(KERN_WARNING
|
||||
" i2c: unregister_adapter adap [%s] not found.\n",
|
||||
adap->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* detach any active clients */
|
||||
for (j=0;j<I2C_CLIENT_MAX;j++) {
|
||||
struct i2c_client *client = adap->clients[j];
|
||||
if ( (client!=NULL)
|
||||
/* && (client->driver->flags & DF_NOTIFY) */ )
|
||||
/* detaching devices is unconditional of the set notify
|
||||
* flag, as _all_ clients that reside on the adapter
|
||||
* must be deleted, as this would cause invalid states.
|
||||
*/
|
||||
client->driver->detach_client(client);
|
||||
/* i2c_detach_client(client); --- frodo */
|
||||
}
|
||||
/* all done, now unregister */
|
||||
adapters[i] = NULL;
|
||||
adap_count--;
|
||||
|
||||
DEB(printk("i2c: adapter unregistered: %s\n",adap->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----
|
||||
* What follows is the "upwards" interface: commands for talking to clients,
|
||||
* which implement the functions to access the physical information of the
|
||||
* chips.
|
||||
*/
|
||||
|
||||
int i2c_add_driver(struct i2c_driver *driver)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_DRIVER_MAX; i++)
|
||||
if (NULL == drivers[i])
|
||||
break;
|
||||
if (I2C_DRIVER_MAX == i) {
|
||||
printk(KERN_WARNING
|
||||
" i2c: register_driver(%s) - enlarge I2C_DRIVER_MAX.\n",
|
||||
driver->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drivers[i] = driver;
|
||||
driver_count++;
|
||||
|
||||
DEB(printk("i2c: driver %s registered.\n",driver->name));
|
||||
|
||||
/* now look for instances of driver on our adapters
|
||||
*/
|
||||
if ( driver->flags&DF_NOTIFY )
|
||||
for (i=0;i<I2C_ADAP_MAX;i++)
|
||||
if (adapters[i]!=NULL)
|
||||
driver->attach_adapter(adapters[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_del_driver(struct i2c_driver *driver)
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
for (i = 0; i < I2C_DRIVER_MAX; i++)
|
||||
if (driver == drivers[i])
|
||||
break;
|
||||
if (I2C_DRIVER_MAX == i) {
|
||||
printk(KERN_WARNING " i2c: unregister_driver: [%s] not found\n",
|
||||
driver->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Have a look at each adapter, if clients of this driver are still
|
||||
* attached. If so, detach them to be able to kill the driver afterwards.
|
||||
*/
|
||||
DEB2(printk("i2c: unregister_driver - looking for clients.\n"));
|
||||
/* removing clients does not depend on the notify flag, else
|
||||
* invalid operation might (will!) result, when using stale client
|
||||
* pointers.
|
||||
*/
|
||||
for (k=0;k<I2C_ADAP_MAX;k++) {
|
||||
struct i2c_adapter *adap = adapters[k];
|
||||
if (adap == NULL) /* skip empty entries. */
|
||||
continue;
|
||||
DEB2(printk("i2c: examining adapter %s:\n",adap->name));
|
||||
for (j=0;j<I2C_CLIENT_MAX;j++) {
|
||||
struct i2c_client *client = adap->clients[j];
|
||||
if (client != NULL && client->driver == driver) {
|
||||
DEB2(printk("i2c: detaching client %s:\n",
|
||||
client->name));
|
||||
/*i2c_detach_client(client);*/
|
||||
driver->detach_client(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
drivers[i] = NULL;
|
||||
driver_count--;
|
||||
|
||||
DEB(printk("i2c: driver unregistered: %s\n",driver->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int i2c_attach_client(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct i2c_algorithm *algo = adapter->algo;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_CLIENT_MAX; i++)
|
||||
if (NULL == adapter->clients[i])
|
||||
break;
|
||||
if (I2C_CLIENT_MAX == i) {
|
||||
printk(KERN_WARNING
|
||||
" i2c: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
|
||||
client->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
adapter->clients[i] = client;
|
||||
adapter->client_count++;
|
||||
if (algo->client_register != NULL)
|
||||
algo->client_register(client);
|
||||
DEB(printk("i2c: client [%s] registered to adapter [%s](pos. %d).\n",
|
||||
client->name, adapter->name,i));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int i2c_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct i2c_algorithm *algo = adapter->algo;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_CLIENT_MAX; i++)
|
||||
if (client == adapter->clients[i])
|
||||
break;
|
||||
if (I2C_CLIENT_MAX == i) {
|
||||
printk(KERN_WARNING " i2c: unregister_client [%s] not found\n",
|
||||
client->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (algo->client_unregister != NULL)
|
||||
algo->client_unregister(client);
|
||||
/* client->driver->detach_client(client);*/
|
||||
adapter->clients[i] = NULL;
|
||||
adapter->client_count--;
|
||||
DEB(printk("i2c: client [%s] unregistered.\n",client->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_init(void)
|
||||
{
|
||||
/* clear algorithms */
|
||||
memset(algorithms,0,sizeof(algorithms));
|
||||
memset(adapters,0,sizeof(adapters));
|
||||
memset(drivers,0,sizeof(drivers));
|
||||
algo_count=0;
|
||||
adap_count=0;
|
||||
driver_count=0;
|
||||
|
||||
printk("i2c module initialized.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------
|
||||
* the functional interface to the i2c busses.
|
||||
* ----------------------------------------------------
|
||||
*/
|
||||
|
||||
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEB2(printk("master_xfer: %s with %d msgs.\n",adap->name,num));
|
||||
|
||||
I2C_LOCK(adap);
|
||||
ret = adap->algo->master_xfer(adap,msgs,num);
|
||||
I2C_UNLOCK(adap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags & ( I2C_M_TEN|I2C_M_TENMASK );
|
||||
msg.len = count;
|
||||
(const char *)msg.buf = buf;
|
||||
|
||||
DEB2(printk("master_send: writing %d bytes on %s.\n",
|
||||
count,client->adapter->name));
|
||||
|
||||
I2C_LOCK(adap);
|
||||
ret = adap->algo->master_xfer(adap,&msg,1);
|
||||
I2C_UNLOCK(adap);
|
||||
|
||||
/* if everything went ok (i.e. 1 msg transmitted), return #bytes
|
||||
* transmitted, else error code.
|
||||
*/
|
||||
return (ret == 1 )? count : ret;
|
||||
}
|
||||
|
||||
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
int ret;
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags & ( I2C_M_TEN|I2C_M_TENMASK );
|
||||
msg.flags |= I2C_M_RD;
|
||||
msg.len = count;
|
||||
msg.buf = buf;
|
||||
|
||||
DEB2(printk("master_recv: reading %d bytes on %s.\n",
|
||||
count,client->adapter->name));
|
||||
|
||||
I2C_LOCK(adap);
|
||||
ret = adap->algo->master_xfer(adap,&msg,1);
|
||||
I2C_UNLOCK(adap);
|
||||
|
||||
/* if everything went ok (i.e. 1 msg transmitted), return #bytes
|
||||
* transmitted, else error code.
|
||||
*/
|
||||
return (ret == 1 )? count : ret;
|
||||
}
|
||||
|
||||
|
||||
int i2c_control(struct i2c_client *client,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
|
||||
DEB2(printk("i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg));
|
||||
switch ( cmd ) {
|
||||
case I2C_RETRIES:
|
||||
adap->retries = arg;
|
||||
break;
|
||||
case I2C_TIMEOUT:
|
||||
adap->timeout = arg;
|
||||
break;
|
||||
default:
|
||||
if (adap->algo->algo_control!=NULL)
|
||||
ret = adap->algo->algo_control(adap,cmd,arg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_probe(struct i2c_client *client, int low_addr, int hi_addr)
|
||||
{
|
||||
int i;
|
||||
struct i2c_msg msg;
|
||||
msg.flags=client->flags & (I2C_M_TENMASK | I2C_M_TEN );
|
||||
msg.buf = NULL;
|
||||
msg.len = 0;
|
||||
I2C_LOCK(client->adapter);
|
||||
for (i = low_addr; i <= hi_addr; i++) {
|
||||
msg.addr=i;
|
||||
/* TODO: implement a control statement in the algo layer
|
||||
* that does address lookup only.
|
||||
*/
|
||||
if (1 == client->adapter->
|
||||
algo->master_xfer(client->adapter,&msg,1))
|
||||
break;
|
||||
}
|
||||
I2C_UNLOCK(client->adapter);
|
||||
return (i <= hi_addr) ? (client->addr=i) : -1;
|
||||
}
|
||||
/* +++ frodo
|
||||
* return id number for a specific adapter
|
||||
*/
|
||||
int i2c_adapter_id(struct i2c_adapter *adap)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < I2C_ADAP_MAX; i++)
|
||||
if (adap == adapters[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus main module");
|
||||
MODULE_PARM(i2c_debug, "i");
|
||||
MODULE_PARM_DESC(i2c_debug,"debug level");
|
||||
|
||||
#ifndef LM_SENSORS
|
||||
EXPORT_SYMBOL(i2c_add_algorithm);
|
||||
EXPORT_SYMBOL(i2c_del_algorithm);
|
||||
EXPORT_SYMBOL(i2c_add_adapter);
|
||||
EXPORT_SYMBOL(i2c_del_adapter);
|
||||
EXPORT_SYMBOL(i2c_add_driver);
|
||||
EXPORT_SYMBOL(i2c_del_driver);
|
||||
EXPORT_SYMBOL(i2c_attach_client);
|
||||
EXPORT_SYMBOL(i2c_detach_client);
|
||||
|
||||
EXPORT_SYMBOL(i2c_master_send);
|
||||
EXPORT_SYMBOL(i2c_master_recv);
|
||||
EXPORT_SYMBOL(i2c_control);
|
||||
EXPORT_SYMBOL(i2c_transfer);
|
||||
#endif
|
||||
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_init();
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
-366
@@ -1,366 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* i2c-dev.c - i2c-bus driver, char device interface */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define RCSID "$Id: i2c-dev.c,v 1.7 1998/12/30 08:36:08 i2c Exp i2c $"
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/malloc.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
# include <asm/uaccess.h>
|
||||
#else
|
||||
# include <asm/segment.h>
|
||||
#endif
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
/* ----- global defines ---------------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEBE(x) x /* error messages ~ */
|
||||
#define DEBI(x) /* ioctl and its arguments */
|
||||
|
||||
/* ----- global variables -------------------------------------------------- */
|
||||
|
||||
/* save the registered char devices.
|
||||
* there is one device per i2c adapter.
|
||||
*/
|
||||
#define I2C_DEV_MAX I2C_ADAP_MAX
|
||||
struct i2c_client *devs[I2C_DEV_MAX];
|
||||
int dev_count;
|
||||
|
||||
struct i2c_driver driver;
|
||||
struct i2c_client dev_template = {
|
||||
"I2C char device", /* name */
|
||||
-1, /* id */
|
||||
0, /* flags */
|
||||
0, /* address */
|
||||
NULL, /* adapter */
|
||||
&driver, /* driver */
|
||||
};
|
||||
|
||||
|
||||
/* ----- local functions --------------------------------------------------- */
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
long long i2c_lseek(struct file * file, long long offset, int origin)
|
||||
#else
|
||||
int i2c_lseek (struct inode * inode, struct file *file, off_t offset, int origin)
|
||||
#endif
|
||||
{
|
||||
return -ESPIPE;
|
||||
}
|
||||
|
||||
|
||||
int i2c_open(struct inode * inode, struct file * file)
|
||||
{
|
||||
unsigned int minor = MINOR(inode->i_rdev);
|
||||
|
||||
if (minor >= dev_count ) {
|
||||
DEBE(printk("i2c: minor exceeded ports\n"));
|
||||
return -ENODEV;
|
||||
}
|
||||
file->private_data = devs[minor];
|
||||
MOD_INC_USE_COUNT;
|
||||
i2c_attach_client(devs[minor]); /* tell adapter it is in use. */
|
||||
|
||||
DEB(printk("i2c_open: i2c%d\n",minor));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
int i2c_release (struct inode * inode, struct file * file)
|
||||
#else
|
||||
void i2c_release (struct inode * inode, struct file * file)
|
||||
#endif
|
||||
{
|
||||
unsigned int minor = MINOR(inode->i_rdev);
|
||||
|
||||
file->private_data=NULL;
|
||||
DEB(printk("i2c_close: i2c%d\n",minor));
|
||||
i2c_detach_client(devs[minor]);
|
||||
MOD_DEC_USE_COUNT;
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020140 /* file operations changed again...*/
|
||||
ssize_t i2c_write(struct file * file,
|
||||
const char * buf, size_t count, loff_t *ppos)
|
||||
#else
|
||||
# if LINUX_VERSION_CODE >= 0x020100
|
||||
long i2c_write(struct inode * inode, struct file * file,
|
||||
const char * buf, unsigned long count)
|
||||
# else
|
||||
int i2c_write (struct inode *inode, struct file *file,
|
||||
const char *buf, int count)
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= 0x020140
|
||||
struct inode *inode = file->f_dentry->d_inode;
|
||||
#endif
|
||||
int ret;
|
||||
char *tmp;
|
||||
unsigned int minor = MINOR(inode->i_rdev);
|
||||
struct i2c_client *client =
|
||||
(struct i2c_client *)file->private_data;
|
||||
|
||||
if (minor>=dev_count){
|
||||
DEBE(printk("i2c_write: minor %d invalid\n",minor));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* copy user space data to kernel space. */
|
||||
tmp = kmalloc(count,GFP_KERNEL);
|
||||
if (tmp==NULL)
|
||||
return -ENOMEM;
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
copy_from_user(tmp,buf,count);
|
||||
#else
|
||||
memcpy_fromfs(tmp,buf,count);
|
||||
#endif
|
||||
|
||||
DEB(printk("i2c_write: i2c%d writing %d bytes.\n",minor,count));
|
||||
|
||||
ret = i2c_master_send(client,tmp,count);
|
||||
kfree(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020140 /* file operations changed again...*/
|
||||
ssize_t i2c_read(struct file * file,char * buf, size_t count, loff_t *ppos)
|
||||
#else
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
long i2c_read(struct inode * inode, struct file * file,
|
||||
char * buf, unsigned long count)
|
||||
#else
|
||||
int i2c_read (struct inode *inode, struct file *file, char *buf, int count)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= 0x020140
|
||||
struct inode *inode = file->f_dentry->d_inode;
|
||||
#endif
|
||||
unsigned int minor = MINOR(inode->i_rdev);
|
||||
struct i2c_client *client =
|
||||
(struct i2c_client *)file->private_data;
|
||||
char *tmp;
|
||||
int ret;
|
||||
|
||||
DEB(printk("i2c_read: i2c%d reading %d bytes from %d.\n",minor,count,client->addr));
|
||||
if (minor>=dev_count) {
|
||||
DEBE(printk("i2c_write: minor %d invalid\n",minor));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* copy user space data to kernel space. */
|
||||
tmp = kmalloc(count,GFP_KERNEL);
|
||||
if (tmp==NULL)
|
||||
return -ENOMEM;
|
||||
ret = i2c_master_recv(client,tmp,count);
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
copy_to_user(buf,tmp,count);
|
||||
#else
|
||||
memcpy_tofs(buf,tmp,count);
|
||||
#endif
|
||||
kfree(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int i2c_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int minor = MINOR(inode->i_rdev);
|
||||
struct i2c_client *client =
|
||||
(struct i2c_client *)file->private_data;
|
||||
int ret = 0;
|
||||
|
||||
DEBI(printk("i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg));
|
||||
switch ( cmd ) {
|
||||
case I2C_SLAVE:
|
||||
client->addr = arg;
|
||||
break;
|
||||
case I2C_TENBIT:
|
||||
client->flags &= !I2C_M_TENMASK;
|
||||
if (arg<0)
|
||||
return 0;
|
||||
switch(arg) {
|
||||
case 0:
|
||||
client->flags|=I2C_M_TEN0;
|
||||
break;
|
||||
case 1:
|
||||
client->flags|=I2C_M_TEN1;
|
||||
break;
|
||||
case 2:
|
||||
client->flags|=I2C_M_TEN2;
|
||||
break;
|
||||
case 3:
|
||||
client->flags|=I2C_M_TEN3;
|
||||
break;
|
||||
default:
|
||||
printk("i2c-dev(%d): illegal arg to I2C_TEN: %ld\n"
|
||||
,minor,arg);
|
||||
};
|
||||
break;
|
||||
#if 0
|
||||
case I2C_WRITE_SIZE:
|
||||
if ( arg >= I2C_BUFFER_SIZE ) {
|
||||
printk("i2c%d: write size too big (%ld)",minor,arg);
|
||||
return -E2BIG;
|
||||
}
|
||||
data->writelength = arg;
|
||||
if ( arg > 0 )
|
||||
i2c_table[minor].flags|= P_REG;
|
||||
else
|
||||
i2c_table[minor].flags&=!P_REG;
|
||||
break;
|
||||
case I2C_WRITE_BUF:
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
copy_from_user(data->buf,(char*)arg,data->writelength);
|
||||
#else
|
||||
memcpy_fromfs(data->buf,(char*)arg,data->writelength);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = i2c_control(client,cmd,arg);
|
||||
}
|
||||
DEB(printk("i2c(dev): handled ioctl (%d,%ld)\n",cmd,arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ----- module functions --------------------------------------------- */
|
||||
struct file_operations i2c_fops = {
|
||||
i2c_lseek,
|
||||
i2c_read,
|
||||
i2c_write,
|
||||
NULL, /* i2c_readdir */
|
||||
NULL, /* i2c_select */
|
||||
i2c_ioctl,
|
||||
NULL, /* i2c_mmap */
|
||||
i2c_open,
|
||||
#if LINUX_VERSION_CODE >= 0x020178
|
||||
NULL, /* i2c_flush */
|
||||
#endif
|
||||
i2c_release,
|
||||
};
|
||||
|
||||
int attach_adapter(struct i2c_adapter *adap)
|
||||
{
|
||||
int i;
|
||||
struct i2c_client *client;
|
||||
|
||||
for (i = 0; i < I2C_DEV_MAX; i++)
|
||||
if (NULL == devs[i])
|
||||
break;
|
||||
if (I2C_DEV_MAX == i)
|
||||
return -ENOMEM;
|
||||
|
||||
client = (struct i2c_client *)kmalloc(sizeof(struct i2c_client),
|
||||
GFP_KERNEL);
|
||||
if (client==NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(client,&dev_template,sizeof(struct i2c_client));
|
||||
client->adapter = adap;
|
||||
/* for combined r/w:
|
||||
client->data = kmalloc(sizeof(char)*I2C_BUFFER_SIZE,GFP_KERNEL);
|
||||
*/
|
||||
devs[i] = client;
|
||||
dev_count++;
|
||||
|
||||
DEB(printk("i2c(char): registered '%s' as minor %d\n",adap->name,i));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int detach_adapter(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
int i;
|
||||
for (i = 0; i < I2C_DEV_MAX; i++)
|
||||
if (devs[i]->adapter == adap)
|
||||
break;
|
||||
if (I2C_DEV_MAX == i)
|
||||
{
|
||||
printk(KERN_WARNING "i2c(char): detach adapter %s not found\n",
|
||||
adap->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (devs[i]->data)
|
||||
kfree(devs[i]->data);
|
||||
kfree(devs[i]);
|
||||
devs[i] = NULL;
|
||||
dev_count--;
|
||||
|
||||
DEB(printk("i2c(char): adapter unregistered: %s\n",adap->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int command(struct i2c_client *client,unsigned int cmd, void *arg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct i2c_driver driver = {
|
||||
"i2c character device",
|
||||
2, /* id */
|
||||
DF_NOTIFY, /* flags */
|
||||
attach_adapter,
|
||||
detach_adapter,
|
||||
command,
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus character device interface");
|
||||
|
||||
#ifndef LM_SENSORS
|
||||
EXPORT_NO_SYMBOLS;
|
||||
#endif
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
if (register_chrdev(I2C_MAJOR,"i2c",&i2c_fops)) {
|
||||
printk("i2c: unable to get major %d for i2c bus\n",I2C_MAJOR);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memset(&devs,0,sizeof(devs));
|
||||
dev_count = 0;
|
||||
|
||||
i2c_add_driver(&driver);
|
||||
printk("i2c char device interface initialized.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_del_driver(&driver);
|
||||
unregister_chrdev(I2C_MAJOR,"i2c");
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,382 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* */
|
||||
/* i2c.h - definitions for the \iic-bus interface */
|
||||
/* */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#ifndef _I2C_H
|
||||
#define _I2C_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* define spinlock to use spinlocks for sync., else use semaphores*/
|
||||
/*#define I2C_SPINLOCK*/
|
||||
|
||||
#ifdef I2C_SPINLOCK
|
||||
#include <asm/spinlock.h> /* for spinlock_t */
|
||||
#else
|
||||
#include <asm/page.h> /* Needed for 2.2 kernels */
|
||||
#if LINUX_VERSION_CODE < 0x020019
|
||||
#include <linux/sched.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#endif
|
||||
/* --- General options ------------------------------------------------ */
|
||||
|
||||
#define I2C_ALGO_MAX 4 /* control memory consumption */
|
||||
#define I2C_ADAP_MAX 16
|
||||
#define I2C_DRIVER_MAX 16
|
||||
#define I2C_CLIENT_MAX 32
|
||||
|
||||
struct i2c_msg;
|
||||
struct i2c_algorithm;
|
||||
struct i2c_adapter;
|
||||
struct i2c_client;
|
||||
struct i2c_driver;
|
||||
|
||||
|
||||
/*
|
||||
* The master routines are the ones normally used to transmit data to devices
|
||||
* on a bus (or read from them). Apart from two basic transfer functions to transmit
|
||||
* one message at a time, a more complex version can be used to transmit an arbitrary
|
||||
* number of messages without interruption.
|
||||
*/
|
||||
extern int i2c_master_send(struct i2c_client *,const char* ,int);
|
||||
extern int i2c_master_recv(struct i2c_client *,char* ,int);
|
||||
|
||||
/* Transfer num messages.
|
||||
*/
|
||||
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num);
|
||||
|
||||
|
||||
/*
|
||||
* Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor.
|
||||
* This is not tested/implemented yet and will change in the future.
|
||||
*/
|
||||
extern int i2c_slave_send(struct i2c_client *,char*,int);
|
||||
extern int i2c_slave_recv(struct i2c_client *,char*,int);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* I2C Message - could be used in the current interface to
|
||||
*/
|
||||
struct i2c_msg {
|
||||
unsigned char addr; /* slave address */
|
||||
unsigned short flags;
|
||||
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
|
||||
#define I2C_M_TEN0 0x10 /* herein lie the first 2 bits */
|
||||
#define I2C_M_TEN1 0x12
|
||||
#define I2C_M_TEN2 0x14
|
||||
#define I2C_M_TEN3 0x16
|
||||
#define I2C_M_TENMASK 0x06
|
||||
#define I2C_M_RD 0x01
|
||||
short len; /* msg length */
|
||||
char *buf; /* pointer to msg data */
|
||||
};
|
||||
|
||||
/*
|
||||
* A driver is capable of handling one or more physical devices present on
|
||||
* I2C adapters. This information is used to inform the driver of adapter
|
||||
* events.
|
||||
*/
|
||||
|
||||
struct i2c_driver {
|
||||
char name[32];
|
||||
int id;
|
||||
unsigned int flags; /* div., see below */
|
||||
|
||||
/* notifies the driver that a new bus has appeared. This routine
|
||||
* can be used by the driver to test if the bus meets its conditions
|
||||
* & seek for the presence of the chip(s) it supports. If found, it
|
||||
* registers the client(s) that are on the bus to the i2c admin. via
|
||||
* i2c_attach_client
|
||||
*/
|
||||
int (*attach_adapter)(struct i2c_adapter *);
|
||||
|
||||
/* tells the driver that a client is about to be deleted & gives it
|
||||
* the chance to remove its private data. Also, if the client struct
|
||||
* has been dynamically allocated by the driver in the function above,
|
||||
* it must be freed here.
|
||||
*/
|
||||
int (*detach_client)(struct i2c_client *);
|
||||
|
||||
/* a ioctl like command that can be used to perform specific functions
|
||||
* with the device.
|
||||
*/
|
||||
int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
|
||||
|
||||
/* These two are mainly used for bookkeeping & dynamic unloading of
|
||||
* kernel modules. inc_use tells the driver that a client is being
|
||||
* used by another module & that it should increase its ref. counter.
|
||||
* dec_use is the inverse operation.
|
||||
* NB: Make sure you have no circular dependencies, or else you get a
|
||||
* deadlock when trying to unload the modules.
|
||||
*/
|
||||
void (*inc_use)(struct i2c_client *client);
|
||||
void (*dec_use)(struct i2c_client *client);
|
||||
};
|
||||
|
||||
/*
|
||||
* i2c_client identifies a single device (i.e. chip) that is connected to an
|
||||
* i2c bus. The behaviour is defined by the routines of the driver. This
|
||||
* function is mainly used for lookup & other admin. functions.
|
||||
*/
|
||||
struct i2c_client {
|
||||
char name[32];
|
||||
int id;
|
||||
unsigned int flags; /* div., see below */
|
||||
unsigned char addr; /* chip address - NOTE: 7bit */
|
||||
/* addresses are stored in the */
|
||||
/* _LOWER_ 7 bits of this char */
|
||||
/* 10 bit addresses use the full*/
|
||||
/* 8 bits & the flags like in */
|
||||
/* i2c_msg */
|
||||
struct i2c_adapter *adapter; /* the adapter we sit on */
|
||||
struct i2c_driver *driver; /* and our access routines */
|
||||
void *data; /* for the clients */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The following structs are for those who like to implement new bus drivers:
|
||||
* i2c_algorithm is the interface to a class of hardware solutions which can
|
||||
* be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
|
||||
* to name two of the most common.
|
||||
*/
|
||||
struct i2c_algorithm {
|
||||
char name[32]; /* textual description */
|
||||
unsigned int id;
|
||||
/*
|
||||
int (*master_send)(struct i2c_client *,const char*,int);
|
||||
int (*master_recv)(struct i2c_client *,char*,int);
|
||||
int (*master_comb)(struct i2c_client *,char*,const char*,int,int,int);
|
||||
*/
|
||||
int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[], int num);
|
||||
|
||||
/* --- these optional/future use for some adapter types.*/
|
||||
int (*slave_send)(struct i2c_adapter *,char*,int);
|
||||
int (*slave_recv)(struct i2c_adapter *,char*,int);
|
||||
|
||||
/* --- ioctl like call to set div. parameters. */
|
||||
int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
|
||||
|
||||
/* --- administration stuff. */
|
||||
int (*client_register)(struct i2c_client *);
|
||||
int (*client_unregister)(struct i2c_client *);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* i2c_adapter is the structure used to identify a physical i2c bus along
|
||||
* with the access algorithms necessary to access it.
|
||||
*/
|
||||
struct i2c_adapter {
|
||||
char name[32]; /* some useful name to identify the adapter */
|
||||
unsigned int id;/* == is algo->id | hwdep.struct->id, */
|
||||
/* for registered values see below */
|
||||
struct i2c_algorithm *algo;/* the algorithm to access the bus */
|
||||
|
||||
void *data; /* private data for the adapter */
|
||||
/* some data fields that are used by all types */
|
||||
/* these data fields are readonly to the public */
|
||||
/* and can be set via the i2c_ioctl call */
|
||||
|
||||
/* data fields that are valid for all devices */
|
||||
#ifdef I2C_SPINLOCK
|
||||
spinlock_t lock;/* used to access the adapter exclusively */
|
||||
unsigned long lockflags;
|
||||
#else
|
||||
struct semaphore lock;
|
||||
#endif
|
||||
unsigned int flags;/* flags specifying div. data */
|
||||
|
||||
struct i2c_client *clients[I2C_CLIENT_MAX];
|
||||
int client_count;
|
||||
|
||||
int timeout;
|
||||
int retries;
|
||||
};
|
||||
|
||||
|
||||
/*flags for the driver struct:
|
||||
*/
|
||||
#define DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */
|
||||
|
||||
|
||||
/* ----- functions exported by i2c.o */
|
||||
|
||||
/* administration...
|
||||
*/
|
||||
extern int i2c_add_algorithm(struct i2c_algorithm *);
|
||||
extern int i2c_del_algorithm(struct i2c_algorithm *);
|
||||
|
||||
extern int i2c_add_adapter(struct i2c_adapter *);
|
||||
extern int i2c_del_adapter(struct i2c_adapter *);
|
||||
|
||||
extern int i2c_add_driver(struct i2c_driver *);
|
||||
extern int i2c_del_driver(struct i2c_driver *);
|
||||
|
||||
extern int i2c_attach_client(struct i2c_client *);
|
||||
extern int i2c_detach_client(struct i2c_client *);
|
||||
|
||||
|
||||
/*
|
||||
* A utility function used in the attach-phase of drivers. Returns at the first address
|
||||
* that acks in the given range.
|
||||
*/
|
||||
extern int i2c_probe(struct i2c_client *client, int low_addr, int hi_addr);
|
||||
|
||||
/* An ioctl like call to set div. parameters of the adapter.
|
||||
*/
|
||||
extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
|
||||
|
||||
/* This call returns a unique low identifier for each registered adapter,
|
||||
* or -1 if the adapter was not regisitered.
|
||||
*/
|
||||
extern int i2c_adapter_id(struct i2c_adapter *adap);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
||||
/* ----- commands for the ioctl like i2c_command call:
|
||||
* note that additional calls are defined in the algorithm and hw
|
||||
* dependent layers - these can be listed here, or see the
|
||||
* corresponding header files.
|
||||
*/
|
||||
/* -> bit-adapter specific ioctls */
|
||||
#define I2C_RETRIES 0x0701 /* number times a device adress should */
|
||||
/* be polled when not acknowledging */
|
||||
#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
|
||||
|
||||
|
||||
/* this is for i2c-dev.c */
|
||||
#define I2C_SLAVE 0x0703 /* Change slave address */
|
||||
/* Attn.: Slave address is 7 bits long, */
|
||||
/* these are to be passed as the */
|
||||
/* lowest 7 bits in the arg. */
|
||||
/* for 10-bit addresses pass lower 8bits*/
|
||||
#define I2C_TENBIT 0x0704 /* with 0-3 as arg to this call */
|
||||
/* a value <0 resets to 7 bits */
|
||||
/* ... algo-bit.c recognizes */
|
||||
#define I2C_UDELAY 0x0705 /* set delay in microsecs between each */
|
||||
/* written byte (except address) */
|
||||
#define I2C_MDELAY 0x0706 /* millisec delay between written bytes */
|
||||
|
||||
#if 0
|
||||
#define I2C_ADDR 0x0707 /* Change adapter's \iic address */
|
||||
/* ...not supported by all adap's */
|
||||
|
||||
#define I2C_RESET 0x07fd /* reset adapter */
|
||||
#define I2C_CLEAR 0x07fe /* when lost, use to clear stale info */
|
||||
#define I2C_V_SLOW 0x07ff /* set jiffies delay call with int */
|
||||
|
||||
#define I2C_INTR 0x0708 /* Pass interrupt number - 2be impl. */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ---- Driver types -----------------------------------------------------
|
||||
*/
|
||||
|
||||
#define I2C_DRIVERID_MSP3400 1
|
||||
#define I2C_DRIVERID_TUNER 2
|
||||
#define I2C_DRIVERID_VIDEOTEXT 3
|
||||
#define I2C_DRIVERID_GL518SM 4 /* hardware monitor cpu temp. */
|
||||
#define I2C_DRIVERID_TEA6420 5 /* audio matrix switch */
|
||||
#define I2C_DRIVERID_TEA6415 6 /* video matrix switch */
|
||||
#define I2C_DRIVERID_TDA9840 7 /* stereo sound processor */
|
||||
#define I2C_DRIVERID_SAA7111 8 /* video input processor */
|
||||
#define I2C_DRIVERID_BT848 9 /* video input processor */
|
||||
|
||||
#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
|
||||
#define I2C_DRIVERID_EXP1 0xF1
|
||||
#define I2C_DRIVERID_EXP2 0xF2
|
||||
#define I2C_DRIVERID_EXP3 0xF3
|
||||
|
||||
/*
|
||||
* ---- Adapter types ----------------------------------------------------
|
||||
*
|
||||
* First, we distinguish between several algorithms to access the hardware
|
||||
* interface types, as a PCF 8584 needs other care than a bit adapter.
|
||||
*/
|
||||
|
||||
#define ALGO_NONE 0x000000
|
||||
#define ALGO_BIT 0x010000 /* bit style adapters */
|
||||
#define ALGO_PCF 0x020000 /* PCF 8584 style adapters */
|
||||
|
||||
#define ALGO_EXP 0x800000 /* experimental */
|
||||
|
||||
#define ALGO_MASK 0xff0000 /* Mask for algorithms */
|
||||
#define ALGO_SHIFT 0x10 /* right shift to get index values */
|
||||
|
||||
#define I2C_HW_ADAPS 0x10000 /* number of different hw implements per*/
|
||||
/* algorithm layer module */
|
||||
#define I2C_HW_MASK 0xffff /* space for indiv. hw implmentations */
|
||||
|
||||
|
||||
/* hw specific modules that are defined per algorithm layer
|
||||
*/
|
||||
|
||||
/* --- Bit algorithm adapters */
|
||||
#define HW_B_LP 0x00 /* Parallel port Philips style adapter */
|
||||
#define HW_B_LPC 0x01 /* Parallel port, over control reg. */
|
||||
#define HW_B_SER 0x02 /* Serial line interface */
|
||||
#define HW_B_ELV 0x03 /* ELV Card */
|
||||
#define HW_B_VELLE 0x04 /* Vellemann K8000 */
|
||||
#define HW_B_BT848 0x05 /* BT848 video boards */
|
||||
#define HW_B_WNV 0x06 /* Winnov Videums */
|
||||
#define HW_B_VIA 0x07 /* Via vt82c586b */
|
||||
#define HW_B_HYDRA 0x08 /* Apple Hydra Mac I/O */
|
||||
|
||||
/* --- PCF 8584 based algorithms */
|
||||
#define HW_P_LP 0x00 /* Parallel port interface */
|
||||
#define HW_P_ISA 0x01 /* generic ISA Bus interface card */
|
||||
#define HW_P_ELEK 0x02 /* Elektor ISA Bus interface card */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ----- I2C-DEV: char device interface stuff ------------------------- */
|
||||
|
||||
#define I2C_MAJOR 89 /* Device major number */
|
||||
|
||||
|
||||
# if LINUX_VERSION_CODE < 0x020100
|
||||
/* Hack to make this thing compile under 2.0.xx kernels
|
||||
*/
|
||||
|
||||
# ifdef MODULE
|
||||
# define MODULE_AUTHOR(noone)
|
||||
# define MODULE_DESCRIPTION(none)
|
||||
# define MODULE_PARM(no,param)
|
||||
# define MODULE_PARM_DESC(no,description)
|
||||
# define EXPORT_SYMBOL(noexport)
|
||||
# define EXPORT_NO_SYMBOLS
|
||||
# endif
|
||||
|
||||
# ifndef NULL
|
||||
# define NULL ( (void *) 0 )
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# ifndef ENODEV
|
||||
# include <asm/errno.h>
|
||||
# endif
|
||||
#endif
|
||||
@@ -1,291 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* adap-bit.c i2c driver algorithms for bit-shift adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char alg_rcsid[] = "$Id: algo-pcf.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE >= 0x020100
|
||||
|
||||
# include <asm/uaccess.h>
|
||||
#else
|
||||
# include <asm/segment.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "algo-pcf.h"
|
||||
|
||||
/* ----- global defines ---------------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) /* error messages */
|
||||
#define DEBI(x) /* ioctl and its arguments */
|
||||
#define DEBACK(x) x /* ack failed message */
|
||||
#define DEBSTAT(x) /* print several statistical values */
|
||||
|
||||
#define DEBPROTO(x) /* debug the protocol by showing transferred bytes*/
|
||||
|
||||
|
||||
/* ----- global variables --------------------------------------------- */
|
||||
|
||||
/* module parameters:
|
||||
*/
|
||||
static int test=0; /* see if the line-setting functions work */
|
||||
static int scan=0; /* have a look at what's hanging 'round */
|
||||
|
||||
/*
|
||||
* This array contains the hw-specific functions for
|
||||
* each port (hardware) type.
|
||||
*/
|
||||
static struct pcf_adapter *pcf_adaps[PCF_ADAP_MAX];
|
||||
static int adap_count;
|
||||
static struct i2c_adapter *i2c_adaps[PCF_ADAP_MAX];
|
||||
|
||||
/* --- setting states on the bus with the right timing: --------------- */
|
||||
|
||||
/*
|
||||
* Sanity check for the adapter hardware - check the reaction of
|
||||
* the bus lines only if it seems to be idle.
|
||||
*/
|
||||
static int test_bus(struct pcf_adapter *adap)
|
||||
{
|
||||
}
|
||||
|
||||
/* ----- Utility functions
|
||||
*/
|
||||
|
||||
|
||||
/* send a message to a client.
|
||||
*/
|
||||
static int pcf_send(struct i2c_client *client,const char *buf, int count)
|
||||
{
|
||||
struct i2c_adapter *adapter=client->adapter;
|
||||
struct pcf_adapter *adap=(struct pcf_adapter*)adapter->data;
|
||||
int ret,i;
|
||||
|
||||
DEB2(printk(" i2c_write: wrote %d bytes.\n",wrcount));
|
||||
return wrcount;
|
||||
}
|
||||
|
||||
|
||||
static int pcf_recv(struct i2c_client *client,char *buf,int count)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct pcf_adapter *adap = (struct pcf_adapter*)adapter->data;
|
||||
unsigned int flags = client->flags;
|
||||
char addr;
|
||||
int ret=0,i,rdcount;
|
||||
|
||||
DEB(printk("i2c(bit): i2c_read: %d byte(s) read.\n", rdcount ));
|
||||
return rdcount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* alpha version of combined transmit
|
||||
*/
|
||||
static int pcf_comb(struct i2c_client *client, char *readbuf,const char *writebuf,
|
||||
int nread, int nwrite, int dir)
|
||||
{
|
||||
/* struct i2c_adapter *adapter = client->adapter;
|
||||
struct pcf_adapter *adap = (struct pcf_adapter*)adapter->data;
|
||||
unsigned int flags = client->flags;
|
||||
char addr;
|
||||
int ret=0,i,rdcount=0,wrcount=0;
|
||||
|
||||
|
||||
DEB(printk("i2c(bit): i2c_read: %d byte(s) read.\n", rdcount ));
|
||||
return wrcount+rdcount;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int algo_control(struct i2c_adapter *adapter,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_register(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct pcf_adapter *adap = (struct pcf_adapter*)adapter->data;
|
||||
|
||||
if (adap->client_register != NULL)
|
||||
return adap->client_register(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_unregister(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct pcf_adapter *adap = (struct pcf_adapter*)adapter->data;
|
||||
|
||||
if (adap->client_unregister != NULL)
|
||||
return adap->client_unregister(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
struct i2c_algorithm pcf_algo = {
|
||||
"PCF 8584 algorithm",
|
||||
ALGO_BIT,
|
||||
pcf_send, /* master_xmit */
|
||||
pcf_recv, /* master_recv */
|
||||
pcf_comb, /* master_comb */
|
||||
NULL, /* slave_xmit */
|
||||
NULL, /* slave_recv */
|
||||
algo_control, /* ioctl */
|
||||
client_register,
|
||||
client_unregister,
|
||||
};
|
||||
|
||||
/*
|
||||
* registering functions to load algorithms at runtime
|
||||
*/
|
||||
int i2c_pcf_add_bus(struct pcf_adapter *adap)
|
||||
{
|
||||
int i,ack;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
|
||||
for (i = 0; i < PCF_ADAP_MAX; i++)
|
||||
if (NULL == pcf_adaps[i])
|
||||
break;
|
||||
if (PCF_ADAP_MAX == i)
|
||||
return -ENOMEM;
|
||||
|
||||
if (test) {
|
||||
int ret = test_bus(adap);
|
||||
if (ret<0)
|
||||
return -ENODEV;
|
||||
}
|
||||
i2c_adap = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
|
||||
if (i2c_adap == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pcf_adaps[i] = adap;
|
||||
adap_count++;
|
||||
DEB(printk("i2c(bit): algorithm %s registered.\n",adap->name));
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
memset(i2c_adap,0,sizeof(struct i2c_adapter));
|
||||
strcpy(i2c_adap->name,adap->name);
|
||||
i2c_adap->id = pcf_algo.id | adap->id;
|
||||
i2c_adap->algo = &pcf_algo;
|
||||
i2c_adap->data = adap;
|
||||
i2c_adap->timeout = 100; /* default values, should */
|
||||
i2c_adap->retries = 3; /* be replaced by defines */
|
||||
i2c_adaps[i] = i2c_adap;
|
||||
i2c_add_adapter(i2c_adap);
|
||||
|
||||
/* scan bus */
|
||||
if (scan) {
|
||||
#if 0
|
||||
printk(KERN_INFO "i2c(bit): scanning bus %s.\n", adap->name);
|
||||
for (i = 0x00; i < 0xff; i+=2) {
|
||||
i2c_start(adap);
|
||||
ack = i2c_outb(adap,i);
|
||||
i2c_stop(adap);
|
||||
if (ack>0) {
|
||||
printk(KERN_INFO
|
||||
"i2c(bit): found chip at addr=0x%2x\n",i>>1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int i2c_pcf_del_bus(struct pcf_adapter *adap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PCF_ADAP_MAX; i++)
|
||||
if ( adap == pcf_adaps[i])
|
||||
break;
|
||||
if ( PCF_ADAP_MAX == i) {
|
||||
printk(KERN_WARNING "i2c(bit): could not unregister bus: %s\n",
|
||||
adap->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pcf_adaps[i] = NULL;
|
||||
i2c_del_adapter(i2c_adaps[i]);
|
||||
kfree(i2c_adaps[i]);
|
||||
i2c_adaps[i] = NULL;
|
||||
adap_count--;
|
||||
DEB(printk("i2c(bit): adapter unregistered: %s\n",adap->name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int algo_pcf_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<PCF_ADAP_MAX;i++) {
|
||||
pcf_adaps[i]=NULL;
|
||||
}
|
||||
adap_count=0;
|
||||
i2c_add_algorithm(&pcf_algo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_PARM(test, "i");
|
||||
MODULE_PARM(scan, "i");
|
||||
|
||||
EXPORT_SYMBOL(i2c_pcf_add_bus);
|
||||
EXPORT_SYMBOL(i2c_pcf_del_bus);
|
||||
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return algo_pcf_init();
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_del_algorithm(&pcf_algo);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* bit-lp.c i2c-hw access for philips style parallel port adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: bit-lp-multi.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
|
||||
#include "i2c.h"
|
||||
#include "algo-bit.h"
|
||||
|
||||
|
||||
#define BIT_LP_MAX 3 /* max. number of addresses to probe */
|
||||
|
||||
struct bit_lp_data {
|
||||
unsigned int base; /* base address */
|
||||
};
|
||||
|
||||
static struct bit_lp_data bit_lp_adaps[BIT_LP_MAX] = {
|
||||
{0,},
|
||||
{0,},
|
||||
{0,},
|
||||
};
|
||||
static int adap_count=0;
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
|
||||
/* ----- printer port defines ------------------------------------------*/
|
||||
/* Pin Port Inverted name */
|
||||
#define I2C_ON 0x20 /* 12 status N paper */
|
||||
/* ... only for phil. not used */
|
||||
#define I2C_SDA 0x80 /* 9 data N data7 */
|
||||
#define I2C_SCL 0x08 /* 17 ctrl N dsel */
|
||||
|
||||
#define I2C_SDAIN 0x80 /* 11 stat Y busy */
|
||||
#define I2C_SCLIN 0x08 /* 15 stat Y enable */
|
||||
|
||||
#define I2C_DMASK 0x7f
|
||||
#define I2C_CMASK 0xf7
|
||||
|
||||
/* --- Convenience defines for the parallel port: */
|
||||
#define BASE bit_lp_adaps[minor].base
|
||||
#define DATA BASE /* Centronics data port */
|
||||
#define STAT (BASE+1) /* Centronics status port */
|
||||
#define CTRL (BASE+2) /* Centronics control port */
|
||||
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
|
||||
static void bit_lp_setscl(int minor, int state)
|
||||
{
|
||||
if (state) {
|
||||
outb(I2C_SCL, CTRL);
|
||||
} else {
|
||||
outb(I2C_CMASK, CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
static void bit_lp_setsda(int minor, int state)
|
||||
{
|
||||
if (state) {
|
||||
outb(I2C_DMASK , DATA);
|
||||
} else {
|
||||
outb(I2C_SDA , DATA);
|
||||
}
|
||||
}
|
||||
|
||||
static int bit_lp_getscl(int minor)
|
||||
{
|
||||
return ( 0 != ( (inb(STAT)) & I2C_SCLIN ) );
|
||||
}
|
||||
|
||||
static int bit_lp_getsda(int minor)
|
||||
{
|
||||
return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) );
|
||||
}
|
||||
|
||||
static int bit_lp_init(int minor)
|
||||
{
|
||||
if (check_region(bit_lp_adaps[minor].base,
|
||||
(bit_lp_adaps[minor].base == 0x3bc)? 3 : 8) < 0 ) {
|
||||
return -ENODEV;
|
||||
} else {
|
||||
request_region(bit_lp_adaps[minor].base,
|
||||
(bit_lp_adaps[minor].base == 0x3bc)? 3 : 8,
|
||||
"i2c (parallel port adapter)");
|
||||
bit_lp_setsda(minor,1);
|
||||
bit_lp_setscl(minor,1);
|
||||
}
|
||||
printk("i2c%d: scl: %d sda %d \n",minor,bit_lp_getscl(minor),bit_lp_getsda(minor));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bit_lp_exit(int minor)
|
||||
{
|
||||
release_region( bit_lp_adaps[minor].base ,
|
||||
(bit_lp_adaps[minor].base == 0x3bc)? 3 : 8 );
|
||||
release_region( bit_lp_adaps[minor].base + 0x0400, 8 );
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
struct bit_adapter bit_lp_ops = {
|
||||
"Philips Parallel port adapter",
|
||||
bit_lp_setscl,
|
||||
bit_lp_setsda,
|
||||
bit_lp_getscl,
|
||||
bit_lp_getsda,
|
||||
bit_lp_init,
|
||||
bit_lp_exit
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
static int base[BIT_LP_MAX+1] = { [0 ... BIT_LP_MAX] = 0 };
|
||||
MODULE_PARM(base, "1-" __MODULE_STRING(BIT_LP_MAX) "i");
|
||||
|
||||
/*
|
||||
EXPORT_SYMBOL(i2c_bit_add_bus);
|
||||
EXPORT_SYMBOL(i2c_bit_del_bus);
|
||||
*/
|
||||
int init_module(void)
|
||||
{
|
||||
/* Work out how many ports we have, then get parport_share to parse
|
||||
the irq values. */
|
||||
unsigned int i;
|
||||
for (i = 0; i < BIT_LP_MAX && base[i]; i++) {
|
||||
bit_lp_adaps[adap_count].base = base[i];
|
||||
if (bit_lp_init(adap_count)==0) {
|
||||
/* i2c_bit_add_bus(struct bit_adapter *algo);*/
|
||||
/* bit_add_adapter();*/
|
||||
adap_count++;
|
||||
}
|
||||
}
|
||||
if (i==0) { /* no values specified -> probe */
|
||||
}
|
||||
|
||||
/* count += probe_one_port(0x3bc, irq[0], dma[0]);
|
||||
count += probe_one_port(0x378, irq[0], dma[0]);
|
||||
count += probe_one_port(0x278, irq[0], dma[0]);
|
||||
*/
|
||||
printk("bit_lp: found %d devices.\n",adap_count);
|
||||
|
||||
if (adap_count==0)
|
||||
return -ENODEV;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<adap_count;i++) {
|
||||
int i2c_bit_del_bus(struct bit_adapter *algo);
|
||||
bit_lp_exit(i);
|
||||
}
|
||||
/* i2c_del_algorithm(&alg_bit_opns);*/
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* pcf-lp.c i2c-hw access for PCF 8584 on bidir. parallel ports */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: pcf-elektor.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
|
||||
/*
|
||||
* $Log: pcf-elektor.c,v $
|
||||
* Revision 1.1 1998/09/05 18:20:09 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.1 1998/01/20 10:01:29 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.2 1997/06/03 06:00:10 i2c
|
||||
* first version that works
|
||||
*
|
||||
* Revision 1.2 1996/11/20 20:20:46 i2c
|
||||
* first version for ISA bus.
|
||||
*
|
||||
* Revision 1.1 1996/11/17 11:00:03 i2c
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "i2c-priv.h"
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
|
||||
#define DEBHW(x) x /* lowest level hardware debug -- log changes of*/
|
||||
/* the bit lines... */
|
||||
|
||||
#define basePort(port) (i2c_table[minor].base+(port))
|
||||
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
|
||||
#if (PCFADAPS) > 1
|
||||
# define Local static
|
||||
#else
|
||||
# define Local inline
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Local int pcf_read (int minor, int adr)
|
||||
{
|
||||
int ret;
|
||||
udelay(10); /* Give the card some time */
|
||||
ret = inb(basePort( (adr!=0) ));/* force max. increment of 1 */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Local void pcf_write (int minor, int adr,char data)
|
||||
{
|
||||
udelay(10); /* Give the card some time */
|
||||
outb(data,basePort( (adr!=0) ));
|
||||
}
|
||||
|
||||
|
||||
Local int pcf_init (int minor)
|
||||
{
|
||||
if (check_region(i2c_table[minor].base, 4) < 0 ) {
|
||||
return -ENODEV;
|
||||
} else {
|
||||
request_region(i2c_table[minor].base, 4, "i2c (Elektor)");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Local void pcf_exit (int minor)
|
||||
{
|
||||
release_region( i2c_table[minor].base, 4 );
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
#if (PCFADAPS) > 1
|
||||
struct i2c_pcf_ops pcf_lp_ops = {
|
||||
pcf_read,
|
||||
pcf_write,
|
||||
pcf_init,
|
||||
pcf_exit
|
||||
};
|
||||
#endif
|
||||
@@ -1,110 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* pcf-isa.c i2c-hw access for PCF 8584 on ISA boards */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-96 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: pcf-isa.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
|
||||
/*
|
||||
* $Log: pcf-isa.c,v $
|
||||
* Revision 1.1 1998/09/05 18:20:09 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.3 1998/01/20 10:01:29 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.2 1996/11/20 20:20:46 i2c
|
||||
* first version for ISA bus.
|
||||
*
|
||||
* Revision 1.1 1996/11/17 11:00:03 i2c
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "i2c-priv.h"
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
|
||||
/* ----- local functions --------------------------------------------------- */
|
||||
|
||||
#if (PCFADAPS) > 1
|
||||
# define Local static
|
||||
#else
|
||||
# define Local inline
|
||||
#endif
|
||||
|
||||
|
||||
Local int pcf_read (int minor, int adr)
|
||||
{
|
||||
if (adr)
|
||||
return inb(BASE + 1); /* read status port */
|
||||
else
|
||||
return inb(BASE); /* read data port */
|
||||
}
|
||||
|
||||
|
||||
Local void pcf_write (int minor, int adr,char data)
|
||||
{
|
||||
if (adr)
|
||||
outb(data, BASE + 1);
|
||||
else
|
||||
outb(data, BASE);
|
||||
}
|
||||
|
||||
|
||||
Local int pcf_init (int minor)
|
||||
{
|
||||
if (check_region(i2c_table[minor].base, 2) < 0 ) {
|
||||
DEBE(printk("i2c_init: Port %#x already in use.\n",
|
||||
i2c_table[minor].base));
|
||||
return -ENODEV;
|
||||
} else {
|
||||
request_region(i2c_table[minor].base, 2,
|
||||
"i2c (ISA bus)");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Local void pcf_exit (int minor)
|
||||
{
|
||||
release_region( i2c_table[minor].base , 2 );
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
#if (PCFADAPS) > 1
|
||||
struct i2c_pcf_ops pcf_isa_ops = {
|
||||
pcf_read,
|
||||
pcf_write,
|
||||
pcf_init,
|
||||
pcf_exit
|
||||
};
|
||||
#endif
|
||||
@@ -1,228 +0,0 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* pcf-lp.c i2c-hw access for PCF 8584 on bidir. parallel ports */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
-----.-.---....------..-.-.---.... Oh bugger! Hope it works this time......
|
||||
|
||||
Copyright (C) 1995-97 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char rcsid[] = "$Id: pcf-lp.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
|
||||
/*
|
||||
* $Log: pcf-lp.c,v $
|
||||
* Revision 1.1 1998/09/05 18:20:09 i2c
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.4 1998/01/20 10:01:29 i2c
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.3 1997/06/15 14:21:37 i2c
|
||||
* removed debugging messages
|
||||
*
|
||||
* Revision 1.2 1997/06/03 06:00:10 i2c
|
||||
* first version that works
|
||||
*
|
||||
* Revision 1.2 1996/11/20 20:20:46 i2c
|
||||
* first version for ISA bus.
|
||||
*
|
||||
* Revision 1.1 1996/11/17 11:00:03 i2c
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "i2c-priv.h"
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) /* should be reasonable open, close &c. */
|
||||
#define DEB2(x) /* low level debugging - very slow */
|
||||
#define DEBE(x) x /* error messages */
|
||||
|
||||
#define DEBHW(x) x /* lowest level hardware debug -- log changes of*/
|
||||
/* the bit lines... */
|
||||
|
||||
#define lpPort(port) (i2c_table[minor].base+(port))
|
||||
|
||||
|
||||
/* ----- local variables ---------------------------------------------- */
|
||||
|
||||
static unsigned char ctrl; /* remember line states */
|
||||
|
||||
/* (re)set line states */
|
||||
#define Strobe(arg) if (!arg) ctrl|= 0x01; else ctrl &=!0x01;\
|
||||
outb_p(ctrl,lpPort(2)) /* Strobe -- pin 1 */
|
||||
#define AutoLF(arg) if (!arg) ctrl|= 0x02; else ctrl &=!0x02;\
|
||||
outb_p(ctrl,lpPort(2)) /* AutoLF -- pin 14 */
|
||||
#define Init(arg) if ( arg) ctrl|= 0x04; else ctrl &=!0x04;\
|
||||
outb(ctrl,lpPort(2)) /* Init -- pin 16 */
|
||||
#define Select(arg) if (!arg) ctrl|= 0x08; else ctrl &=!0x08;\
|
||||
outb_p(ctrl,lpPort(2)) /* Sel. in - pin 17 */
|
||||
/* 0x10 -- Int Enable */
|
||||
#define ReadBit(arg) if(arg) ctrl|= 0x20; else ctrl &=!0x20;\
|
||||
outb_p(ctrl,lpPort(2)) /* direction bit */
|
||||
|
||||
#define inStr() (! (0x01 & inb(lpPort(2)) ) ) /* Strobe -- pin 1 */
|
||||
#define inALF() (! (0x02 & inb(lpPort(2)) ) ) /* AutoLF -- pin 14 */
|
||||
#define inIni() ( (0x04 & inb(lpPort(2)) ) ) /* Init -- pin 16 */
|
||||
#define inSel() (! (0x08 & inb(lpPort(2)) ) ) /* Sel. in - pin 17 */
|
||||
/* 0x10 -- Int Enable */
|
||||
/*
|
||||
#define Argl() printk("(wr-%d cs-%d a0-%d (%#2x, %#2x))\n", \
|
||||
inStr(),inALF(),inIni(),inb(lpPort(0)),inb(lpPort(1)) )
|
||||
*/
|
||||
#define Argl() /**/
|
||||
|
||||
#define wr(arg) Strobe(arg); Argl() /* write line */
|
||||
#define cs(arg) AutoLF(arg); Argl() /* chip select */
|
||||
#define a0(arg) Init (arg); Argl() /* address line */
|
||||
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
/*
|
||||
#if (PCFADAPS) > 1
|
||||
# define Local static
|
||||
#else
|
||||
# define Local inline
|
||||
#endif
|
||||
*/
|
||||
#define Local /**/
|
||||
|
||||
/* --------- okay, I borrowed it. Stays here for debugging.
|
||||
* check the epp status. After a EPP transfer, it should be true that
|
||||
* 1) the TIMEOUT bit (SPP_STR.0) is clear
|
||||
* 2) the READY bit (SPP_STR.7) is set
|
||||
* returns 1 if okay
|
||||
*/
|
||||
static int ex_ppa_check_epp_status(int minor)
|
||||
{
|
||||
char r;
|
||||
inb(STAT);
|
||||
r = inb(STAT);
|
||||
|
||||
if (r & 1) {
|
||||
outb(r, STAT);
|
||||
outb(r&0xfe, STAT);
|
||||
printk("timed out on port 0x%04x\n", BASE);
|
||||
return 0;
|
||||
}
|
||||
if (!(r & 0x80)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Local int pcf_read (int minor, int adr)
|
||||
{
|
||||
int ret;
|
||||
a0(adr);
|
||||
ex_ppa_check_epp_status(minor);
|
||||
ret = inb(lpPort(4));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Local void pcf_write (int minor, int adr,char data)
|
||||
{
|
||||
a0(adr);
|
||||
ex_ppa_check_epp_status(minor);
|
||||
outb(data,lpPort(4));
|
||||
}
|
||||
|
||||
|
||||
Local int pcf_init (int minor)
|
||||
{
|
||||
char ctrl,ecr; /* parallel port registers */
|
||||
|
||||
if (check_region(i2c_table[minor].base, 8) < 0 ) {
|
||||
return -ENODEV;
|
||||
} else {
|
||||
request_region(i2c_table[minor].base, 8, "i2c (pcf-lp)");
|
||||
}
|
||||
|
||||
/* This is the standard detection algorithm for ECP ports */
|
||||
/* now detect, what kind of parallel port we have: */
|
||||
ecr = inb(i2c_table[minor].base+0x402);
|
||||
ctrl= inb(i2c_table[minor].base+0x002);
|
||||
if (ecr!=ctrl) { /* Okay, we seem to have an extended port :) */
|
||||
if (check_region(i2c_table[minor].base + 0x400, 8) < 0 ) {
|
||||
DEBE(printk( "i2c_init, port %#x: ext. ports already in use "
|
||||
"using only standard driver.\n",
|
||||
i2c_table[minor].base));
|
||||
return -ENODEV;
|
||||
} else {
|
||||
if ( (ecr & 0x03) != 0x01 ) { /* FIFO empty? */
|
||||
printk("FIFO not empty\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
outb(0x34,i2c_table[minor].base+0x402);
|
||||
if (inb(i2c_table[minor].base+0x402) != 0x35 ){ /* bits 0,1 readonly */
|
||||
printk("bits 0,1 not rd/only");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Okay, now we should have an ECP-capable printer port */
|
||||
printk("i2c%d: ECP parallel port.\n",minor);
|
||||
request_region(i2c_table[minor].base+0x0400, 3 ,
|
||||
"i2c (Extended Parallel port adapter)");
|
||||
outb(0x94 ,lpPort(0x402)); /* EPP mode */
|
||||
ctrl = inb(CTRL);
|
||||
|
||||
if (i2c_table[minor].irq > 0){ /* enable int. */
|
||||
outb(inb(lpPort(0x402)|0x10), lpPort(0x402));
|
||||
outb(ctrl|0x10,CTRL);
|
||||
}
|
||||
|
||||
ex_ppa_check_epp_status(minor);
|
||||
printk("status reads %2x\n",pcf_read(minor,1));
|
||||
ex_ppa_check_epp_status(minor);
|
||||
printk("data reads %2x\n",pcf_read(minor,0));
|
||||
}
|
||||
} else {
|
||||
printk("i2c%d: Need EPP port. Sorry.\n",minor);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Okay, now it's time to init my data structures */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Local void pcf_exit (int minor)
|
||||
{
|
||||
release_region( i2c_table[minor].base, 8 );
|
||||
release_region( i2c_table[minor].base + 0x0400, 3 );
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Encapsulate the above functions in the correct operations structure.
|
||||
* This is only done when more than one hardware adapter is supported.
|
||||
*/
|
||||
#if (PCFADAPS) > 1
|
||||
struct i2c_pcf_ops pcf_lp_ops = {
|
||||
pcf_read,
|
||||
pcf_write,
|
||||
pcf_init,
|
||||
pcf_exit
|
||||
};
|
||||
#endif
|
||||
@@ -1,72 +0,0 @@
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* PCF 8584 global defines */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Copyright (C) 19996 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* $Id: pcf8584.h,v 1.1 1998/07/29 08:09:51 i2c Exp $
|
||||
* $Log: pcf8584.h,v $
|
||||
* Revision 1.1 1998/07/29 08:09:51 i2c
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* ----- Control register bits ---------------------------------------- */
|
||||
#define PCF_PIN 0x80
|
||||
#define PCF_ESO 0x40
|
||||
#define PCF_ES1 0x20
|
||||
#define PCF_ES2 0x10
|
||||
#define PCF_ENI 0x08
|
||||
#define PCF_STA 0x04
|
||||
#define PCF_STO 0x02
|
||||
#define PCF_ACK 0x01
|
||||
|
||||
/* ----- Status register bits ----------------------------------------- */
|
||||
/*#define PCF_PIN 0x80 as above*/
|
||||
|
||||
#define PCF_INI 0x40 /* 1 if not initialized */
|
||||
#define PCF_STS 0x20
|
||||
#define PCF_BER 0x10
|
||||
#define PCF_AD0 0x08
|
||||
#define PCF_LRB 0x08
|
||||
#define PCF_AAS 0x04
|
||||
#define PCF_LAB 0x02
|
||||
#define PCF_BB 0x01
|
||||
|
||||
/* ----- Chip clock frequencies --------------------------------------- */
|
||||
#define PCF_CLK3 0x00
|
||||
#define PCF_CLK443 0x10
|
||||
#define PCF_CLK6 0x14
|
||||
#define PCF_CLK8 0x18
|
||||
#define PCF_CLK12 0x1c
|
||||
|
||||
/* ----- transmission frequencies ------------------------------------- */
|
||||
#define PCF_TRNS90 0x00 /* 90 kHz */
|
||||
#define PCF_TRNS45 0x01 /* 45 kHz */
|
||||
#define PCF_TRNS11 0x02 /* 11 kHz */
|
||||
#define PCF_TRNS15 0x03 /* 1.5 kHz */
|
||||
|
||||
|
||||
/* ----- Access to internal registers according to ES1,ES2 ------------ */
|
||||
/* they are mapped to the data port ( a0 = 0 ) */
|
||||
/* available when ESO == 0 : */
|
||||
|
||||
#define PCF_OWNADR 0
|
||||
#define PCF_INTREG PCF_ES2
|
||||
#define PCF_CLKREG PCF_ES1
|
||||
|
||||
|
||||
Reference in new issue
Block a user