diff -Naur linux-2.4.25/drivers/i2c/Config.in linux-2.4.25-atmel/drivers/i2c/Config.in --- linux-2.4.25/drivers/i2c/Config.in Wed Feb 18 14:36:31 2004 +++ linux-2.4.25-atmel/drivers/i2c/Config.in Wed Apr 21 18:33:28 2004 @@ -11,6 +11,7 @@ if [ "$CONFIG_I2C_ALGOBIT" != "n" ]; then dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT $CONFIG_PARPORT dep_tristate ' ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT + dep_tristate ' MCS Electronics parport adapter' CONFIG_I2C_MCSELEC $CONFIG_I2C_ALGOBIT dep_tristate ' Velleman K8000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT dep_tristate ' NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200 $CONFIG_I2C_ALGOBIT if [ "$CONFIG_SCx200_I2C" != "n" ]; then diff -Naur linux-2.4.25/drivers/i2c/Makefile linux-2.4.25-atmel/drivers/i2c/Makefile --- linux-2.4.25/drivers/i2c/Makefile Wed Feb 18 14:36:31 2004 +++ linux-2.4.25-atmel/drivers/i2c/Makefile Wed Apr 21 18:33:18 2004 @@ -13,6 +13,7 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o obj-$(CONFIG_I2C_ELV) += i2c-elv.o +obj-$(CONFIG_I2C_MCSELEC) += i2c-mcselec.o obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o diff -Naur linux-2.4.25/drivers/i2c/i2c-mcselec.c linux-2.4.25-atmel/drivers/i2c/i2c-mcselec.c --- linux-2.4.25/drivers/i2c/i2c-mcselec.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.25-atmel/drivers/i2c/i2c-mcselec.c Wed Apr 21 18:36:31 2004 @@ -0,0 +1,224 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-mcselec.c i2c-hw access for MCS Electronics style adapter */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 1995-2000 Simon G. Vogl + Copyright (C) 2004 Sebastian Zagrodzki + + 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +/* $Id: i2c-elv.c,v 1.17 2001/07/29 02:44:25 mds Exp $ */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define DEFAULT_BASE 0x378 +static int base=0; +static unsigned char PortData = 0; +static unsigned char PortStatus = 0; +static unsigned char PortCtl = 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 */ +#define DEBINIT(x) x /* detection status messages */ + +/* --- 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 ---------------------------------------------- */ + + +static void bit_mcselec_setscl(void *data, int state) +{ + if (state) { + PortCtl |= 0x08; + } else { + PortCtl &= 0xf7; + } + outb_p(PortCtl, CTRL); +} + +static void bit_mcselec_setsda(void *data, int state) +{ + if (state) { + PortData &= 0x7f; + } else { + PortData |= 0x80; + } + outb(PortData, DATA); +} + +static int bit_mcselec_getscl(void *data) +{ + return (inb_p(STAT) & 0x08); +} + +static int bit_mcselec_getsda(void *data) +{ + return (inb_p(STAT) & 0x80); +} + +static int bit_mcselec_init(void) +{ + if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) { + return -ENODEV; + } else { + /* test for adapter */ + bit_mcselec_setscl((void*)base, 1); + udelay(400); + if (!bit_mcselec_getscl((void*)base)) { /* SCL should be high */ + DEBINIT(printk(KERN_DEBUG "i2c-mcselec.o: SCL (Error) was low after SCL (Select) set high.\n")); + return -ENODEV; + } else { + bit_mcselec_setscl((void*)base, 0); /* SCL to low */ + udelay(400); + if (bit_mcselec_getscl((void*)base)) { + bit_mcselec_setscl((void*)base, 1); + DEBINIT(printk(KERN_DEBUG "i2c-mcselec.o: SCL (Error) was high after SCL (Select) set low.\n")); + return -ENODEV; + } + } + request_region(base,(base == 0x3bc)? 3 : 8, + "i2c (MCS Electronics adapter)"); + PortData = 0; + PortStatus = 0; + PortCtl = 0; + bit_mcselec_setsda((void*)base,1); + bit_mcselec_setscl((void*)base,1); + } + return 0; +} + +static void __exit bit_mcselec_exit(void) +{ + release_region( base , (base == 0x3bc)? 3 : 8 ); +} + +static int bit_mcselec_reg(struct i2c_client *client) +{ + return 0; +} + +static int bit_mcselec_unreg(struct i2c_client *client) +{ + return 0; +} + +static void bit_mcselec_inc_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +static void bit_mcselec_dec_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_bit_data bit_mcselec_data = { + NULL, + bit_mcselec_setsda, + bit_mcselec_setscl, + bit_mcselec_getsda, + bit_mcselec_getscl, + 40, 40, 50, /* waits, timeout */ +}; + +static struct i2c_adapter bit_mcselec_ops = { + "MCS Electronics parport adapter", + I2C_HW_B_MCSELEC, + NULL, + &bit_mcselec_data, + bit_mcselec_inc_use, + bit_mcselec_dec_use, + bit_mcselec_reg, + bit_mcselec_unreg, +}; + +int __init i2c_bitmcselec_init(void) +{ + printk(KERN_INFO "i2c-mcselec.o: i2c MCS Electronics parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); + if (base==0) { + /* probe some values */ + base=DEFAULT_BASE; + bit_mcselec_data.data=(void*)DEFAULT_BASE; + if (bit_mcselec_init()==0) { + if(i2c_bit_add_bus(&bit_mcselec_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } else { + bit_mcselec_ops.data=(void*)base; + if (bit_mcselec_init()==0) { + if(i2c_bit_add_bus(&bit_mcselec_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } + printk(KERN_DEBUG "i2c-mcselec.o: found device at %#x.\n",base); + return 0; +} + + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE +MODULE_AUTHOR("Sebastian Zagrodzki "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for MCS Electronics parallel port adapter"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); + +int init_module(void) +{ + return i2c_bitmcselec_init(); +} + +void cleanup_module(void) +{ + i2c_bit_del_bus(&bit_mcselec_ops); + bit_mcselec_exit(); +} + +#endif