PageRenderTime 31ms CodeModel.GetById 22ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/i2c/busses/i2c-parport-light.c

https://bitbucket.org/evzijst/gittest
C | 175 lines | 106 code | 32 blank | 37 comment | 18 complexity | aae3d79a3a4046f6b302431bb55a99c0 MD5 | raw file
  1/* ------------------------------------------------------------------------ *
  2 * i2c-parport.c I2C bus over parallel port                                 *
  3 * ------------------------------------------------------------------------ *
  4   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
  5   
  6   Based on older i2c-velleman.c driver
  7   Copyright (C) 1995-2000 Simon G. Vogl
  8   With some changes from:
  9   Frodo Looijaard <frodol@dds.nl>
 10   Ky�sti M�lkki <kmalkki@cc.hut.fi>
 11   
 12   This program is free software; you can redistribute it and/or modify
 13   it under the terms of the GNU General Public License as published by
 14   the Free Software Foundation; either version 2 of the License, or
 15   (at your option) any later version.
 16
 17   This program is distributed in the hope that it will be useful,
 18   but WITHOUT ANY WARRANTY; without even the implied warranty of
 19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20   GNU General Public License for more details.
 21
 22   You should have received a copy of the GNU General Public License
 23   along with this program; if not, write to the Free Software
 24   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 25 * ------------------------------------------------------------------------ */
 26
 27#include <linux/config.h>
 28#include <linux/kernel.h>
 29#include <linux/module.h>
 30#include <linux/init.h>
 31#include <linux/ioport.h>
 32#include <linux/i2c.h>
 33#include <linux/i2c-algo-bit.h>
 34#include <asm/io.h>
 35#include "i2c-parport.h"
 36
 37#define DEFAULT_BASE 0x378
 38
 39static u16 base;
 40module_param(base, ushort, 0);
 41MODULE_PARM_DESC(base, "Base I/O address");
 42
 43/* ----- Low-level parallel port access ----------------------------------- */
 44
 45static inline void port_write(unsigned char p, unsigned char d)
 46{
 47	outb(d, base+p);
 48}
 49
 50static inline unsigned char port_read(unsigned char p)
 51{
 52	return inb(base+p);
 53}
 54
 55/* ----- Unified line operation functions --------------------------------- */
 56
 57static inline void line_set(int state, const struct lineop *op)
 58{
 59	u8 oldval = port_read(op->port);
 60
 61	/* Touch only the bit(s) needed */
 62	if ((op->inverted && !state) || (!op->inverted && state))
 63		port_write(op->port, oldval | op->val);
 64	else
 65		port_write(op->port, oldval & ~op->val);
 66}
 67
 68static inline int line_get(const struct lineop *op)
 69{
 70	u8 oldval = port_read(op->port);
 71
 72	return ((op->inverted && (oldval & op->val) != op->val)
 73	    || (!op->inverted && (oldval & op->val) == op->val));
 74}
 75
 76/* ----- I2C algorithm call-back functions and structures ----------------- */
 77
 78static void parport_setscl(void *data, int state)
 79{
 80	line_set(state, &adapter_parm[type].setscl);
 81}
 82
 83static void parport_setsda(void *data, int state)
 84{
 85	line_set(state, &adapter_parm[type].setsda);
 86}
 87
 88static int parport_getscl(void *data)
 89{
 90	return line_get(&adapter_parm[type].getscl);
 91}
 92
 93static int parport_getsda(void *data)
 94{
 95	return line_get(&adapter_parm[type].getsda);
 96}
 97
 98/* Encapsulate the functions above in the correct structure
 99   Note that getscl will be set to NULL by the attaching code for adapters
100   that cannot read SCL back */
101static struct i2c_algo_bit_data parport_algo_data = {
102	.setsda		= parport_setsda,
103	.setscl		= parport_setscl,
104	.getsda		= parport_getsda,
105	.getscl		= parport_getscl,
106	.udelay		= 50,
107	.mdelay		= 50,
108	.timeout	= HZ,
109}; 
110
111/* ----- I2c structure ---------------------------------------------------- */
112
113static struct i2c_adapter parport_adapter = {
114	.owner		= THIS_MODULE,
115	.class		= I2C_CLASS_HWMON,
116	.id		= I2C_HW_B_LP,
117	.algo_data	= &parport_algo_data,
118	.name		= "Parallel port adapter (light)",
119};
120
121/* ----- Module loading, unloading and information ------------------------ */
122
123static int __init i2c_parport_init(void)
124{
125	int type_count;
126
127	type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
128	if (type < 0 || type >= type_count) {
129		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
130		type = 0;
131	}
132	
133	if (base == 0) {
134		printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
135		base = DEFAULT_BASE;
136	}
137
138	if (!request_region(base, 3, "i2c-parport"))
139		return -ENODEV;
140
141        if (!adapter_parm[type].getscl.val)
142		parport_algo_data.getscl = NULL;
143
144	/* Reset hardware to a sane state (SCL and SDA high) */
145	parport_setsda(NULL, 1);
146	parport_setscl(NULL, 1);
147	/* Other init if needed (power on...) */
148	if (adapter_parm[type].init.val)
149		line_set(1, &adapter_parm[type].init);
150
151	if (i2c_bit_add_bus(&parport_adapter) < 0) {
152		printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
153		release_region(base, 3);
154		return -ENODEV;
155	}
156	
157	return 0;
158}
159
160static void __exit i2c_parport_exit(void)
161{
162	/* Un-init if needed (power off...) */
163	if (adapter_parm[type].init.val)
164		line_set(0, &adapter_parm[type].init);
165
166	i2c_bit_del_bus(&parport_adapter);
167	release_region(base, 3);
168}
169
170MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
171MODULE_DESCRIPTION("I2C bus over parallel port (light)");
172MODULE_LICENSE("GPL");
173
174module_init(i2c_parport_init);
175module_exit(i2c_parport_exit);