linux-old/drivers/i2c/i2c-elv.c
<<
>>
Prefs
   1/* ------------------------------------------------------------------------- */
   2/* i2c-elv.c i2c-hw access for philips style parallel port adapters          */
   3/* ------------------------------------------------------------------------- */
   4/*   Copyright (C) 1995-2000 Simon G. Vogl
   5
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 2 of the License, or
   9    (at your option) any later version.
  10
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15
  16    You should have received a copy of the GNU General Public License
  17    along with this program; if not, write to the Free Software
  18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  19/* ------------------------------------------------------------------------- */
  20
  21/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
  22   Frodo Looijaard <frodol@dds.nl> */
  23
  24/* $Id: i2c-elv.c,v 1.17 2001/07/29 02:44:25 mds Exp $ */
  25
  26#include <linux/kernel.h>
  27#include <linux/module.h>
  28#include <linux/delay.h>
  29#include <linux/slab.h>
  30#include <linux/init.h>
  31
  32#include <asm/uaccess.h>
  33
  34#include <linux/ioport.h>
  35#include <asm/io.h>
  36#include <linux/errno.h>
  37#include <linux/i2c.h>
  38#include <linux/i2c-algo-bit.h>
  39
  40#define DEFAULT_BASE 0x378
  41static int base=0;
  42static unsigned char PortData = 0;
  43
  44/* ----- global defines ----------------------------------------------- */
  45#define DEB(x)          /* should be reasonable open, close &c.         */
  46#define DEB2(x)         /* low level debugging - very slow              */
  47#define DEBE(x) x       /* error messages                               */
  48#define DEBINIT(x) x    /* detection status messages                    */
  49
  50/* --- Convenience defines for the parallel port:                       */
  51#define BASE    (unsigned int)(data)
  52#define DATA    BASE                    /* Centronics data port         */
  53#define STAT    (BASE+1)                /* Centronics status port       */
  54#define CTRL    (BASE+2)                /* Centronics control port      */
  55
  56
  57/* ----- local functions ---------------------------------------------- */
  58
  59
  60static void bit_elv_setscl(void *data, int state)
  61{
  62        if (state) {
  63                PortData &= 0xfe;
  64        } else {
  65                PortData |=1;
  66        }
  67        outb(PortData, DATA);
  68}
  69
  70static void bit_elv_setsda(void *data, int state)
  71{
  72        if (state) {
  73                PortData &=0xfd;
  74        } else {
  75                PortData |=2;
  76        }
  77        outb(PortData, DATA);
  78} 
  79
  80static int bit_elv_getscl(void *data)
  81{
  82        return ( 0 == ( (inb_p(STAT)) & 0x08 ) );
  83}
  84
  85static int bit_elv_getsda(void *data)
  86{
  87        return ( 0 == ( (inb_p(STAT)) & 0x40 ) );
  88}
  89
  90static int bit_elv_init(void)
  91{
  92        if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
  93                return -ENODEV; 
  94        } else {
  95                                                /* test for ELV adap.   */
  96                if (inb(base+1) & 0x80) {       /* BUSY should be high  */
  97                        DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n"));
  98                        return -ENODEV;
  99                } else {
 100                        outb(0x0c,base+2);      /* SLCT auf low         */
 101                        udelay(400);
 102                        if ( !(inb(base+1) && 0x10) ) {
 103                                outb(0x04,base+2);
 104                                DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n"));
 105                                return -ENODEV;
 106                        }
 107                }
 108                request_region(base,(base == 0x3bc)? 3 : 8,
 109                        "i2c (ELV adapter)");
 110                PortData = 0;
 111                bit_elv_setsda((void*)base,1);
 112                bit_elv_setscl((void*)base,1);
 113        }
 114        return 0;
 115}
 116
 117static void __exit bit_elv_exit(void)
 118{
 119        release_region( base , (base == 0x3bc)? 3 : 8 );
 120}
 121
 122static int bit_elv_reg(struct i2c_client *client)
 123{
 124        return 0;
 125}
 126
 127static int bit_elv_unreg(struct i2c_client *client)
 128{
 129        return 0;
 130}
 131
 132static void bit_elv_inc_use(struct i2c_adapter *adap)
 133{
 134#ifdef MODULE
 135        MOD_INC_USE_COUNT;
 136#endif
 137}
 138
 139static void bit_elv_dec_use(struct i2c_adapter *adap)
 140{
 141#ifdef MODULE
 142        MOD_DEC_USE_COUNT;
 143#endif
 144}
 145
 146/* ------------------------------------------------------------------------
 147 * Encapsulate the above functions in the correct operations structure.
 148 * This is only done when more than one hardware adapter is supported.
 149 */
 150static struct i2c_algo_bit_data bit_elv_data = {
 151        NULL,
 152        bit_elv_setsda,
 153        bit_elv_setscl,
 154        bit_elv_getsda,
 155        bit_elv_getscl,
 156        80, 80, 100,            /*      waits, timeout */
 157};
 158
 159static struct i2c_adapter bit_elv_ops = {
 160        "ELV Parallel port adaptor",
 161        I2C_HW_B_ELV,
 162        NULL,
 163        &bit_elv_data,
 164        bit_elv_inc_use,
 165        bit_elv_dec_use,
 166        bit_elv_reg,
 167        bit_elv_unreg,  
 168};
 169
 170int __init i2c_bitelv_init(void)
 171{
 172        printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
 173        if (base==0) {
 174                /* probe some values */
 175                base=DEFAULT_BASE;
 176                bit_elv_data.data=(void*)DEFAULT_BASE;
 177                if (bit_elv_init()==0) {
 178                        if(i2c_bit_add_bus(&bit_elv_ops) < 0)
 179                                return -ENODEV;
 180                } else {
 181                        return -ENODEV;
 182                }
 183        } else {
 184                bit_elv_ops.data=(void*)base;
 185                if (bit_elv_init()==0) {
 186                        if(i2c_bit_add_bus(&bit_elv_ops) < 0)
 187                                return -ENODEV;
 188                } else {
 189                        return -ENODEV;
 190                }
 191        }
 192        printk(KERN_DEBUG "i2c-elv.o: found device at %#x.\n",base);
 193        return 0;
 194}
 195
 196
 197EXPORT_NO_SYMBOLS;
 198
 199#ifdef MODULE
 200MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 201MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
 202MODULE_LICENSE("GPL");
 203
 204MODULE_PARM(base, "i");
 205
 206int init_module(void)
 207{
 208        return i2c_bitelv_init();
 209}
 210
 211void cleanup_module(void)
 212{
 213        i2c_bit_del_bus(&bit_elv_ops);
 214        bit_elv_exit();
 215}
 216
 217#endif
 218
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.