diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /packages/linux/linux-mtx-1-2.4.27/16-i2c.patch | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'packages/linux/linux-mtx-1-2.4.27/16-i2c.patch')
-rw-r--r-- | packages/linux/linux-mtx-1-2.4.27/16-i2c.patch | 7482 |
1 files changed, 0 insertions, 7482 deletions
diff --git a/packages/linux/linux-mtx-1-2.4.27/16-i2c.patch b/packages/linux/linux-mtx-1-2.4.27/16-i2c.patch deleted file mode 100644 index cec737bdfe..0000000000 --- a/packages/linux/linux-mtx-1-2.4.27/16-i2c.patch +++ /dev/null @@ -1,7482 +0,0 @@ ---- linux-old/Documentation/Configure.help Mon Dec 13 16:57:33 2004 -+++ linux/Documentation/Configure.help Mon Dec 13 19:26:23 2004 -@@ -19347,6 +19347,16 @@ - <file:Documentation/modules.txt>. - The module will be called i2c-velleman.o. - -+Basic I2C on Parallel Port adapter -+CONFIG_I2C_PPORT -+ This supports directly connecting I2C devices to the parallel port. -+ See <file:Documentation/i2c/i2c-pport> for more information. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-pport.o. -+ - I2C PCF 8584 interfaces - CONFIG_I2C_ALGOPCF - This allows you to use a range of I2C adapters called PCF adapters. -@@ -19368,6 +19378,15 @@ - <file:Documentation/modules.txt>. - The module will be called i2c-elektor.o. - -+PCF on the EPP Parallel Port -+CONFIG_I2C_PCFEPP -+ This supports the PCF8584 connected to the parallel port. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-pcf-epp.o. -+ - ITE I2C Algorithm - CONFIG_ITE_I2C_ALGO - This supports the use the ITE8172 I2C interface found on some MIPS -@@ -19405,6 +19424,51 @@ - Supports the SGI interfaces like the ones found on SGI Indy VINO - or SGI O2 MACE. - -+Motorola 8xx I2C algorithm -+CONFIG_I2C_ALGO8XX -+ This is the algorithm that allows you to use Motorola 8xx I2C adapters. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-algo-8xx.o. -+ -+Motorola 8xx I2C interface -+CONFIG_I2C_RPXLITE -+ This supports the Motorola 8xx I2C device. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-rpx.o. -+ -+IBM 405 I2C algorithm -+CONFIG_I2C_IBM_OCP_ALGO -+ This is the algorithm that allows you to use IBM 405 I2C adapters. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-algo-ibm_ocp.o. -+ -+IBM 405 I2C interface -+CONFIG_I2C_IBM_OCP_ADAP -+ This supports the IBM 405 I2C device. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-adap-ibm_ocp.o. -+ -+StrongARM SA-1110 interface -+CONFIG_I2C_FRODO -+ This supports the StrongARM SA-1110 Development Board. -+ -+ This driver is also available as a module. If you want to compile -+ it as a module, say M here and read -+ <file:Documentation/modules.txt>. -+ The module will be called i2c-frodo.o. -+ - I2C device interface - CONFIG_I2C_CHARDEV - Say Y here to use i2c-* device files, usually found in the /dev ---- linux-old/Documentation/i2c/dev-interface Mon Dec 22 22:44:34 2003 -+++ linux/Documentation/i2c/dev-interface Mon Dec 13 19:26:23 2004 -@@ -89,6 +89,11 @@ - Selects ten bit addresses if select not equals 0, selects normal 7 bit - addresses if select equals 0. Default 0. - -+ioctl(file,I2C_PEC,long select) -+ Selects SMBus PEC (packet error checking) generation and verification -+ if select not equals 0, disables if select equals 0. Default 0. -+ Used only for SMBus transactions. -+ - ioctl(file,I2C_FUNCS,unsigned long *funcs) - Gets the adapter functionality and puts it in *funcs. - ---- linux-old/Documentation/i2c/i2c-pport Thu Jan 1 00:00:00 1970 -+++ linux/Documentation/i2c/i2c-pport Mon Dec 13 19:26:24 2004 -@@ -0,0 +1,67 @@ -+Parallel Port Adapters -+---------------------- -+If you are installing parallel port adapters it means you are probably messing -+around with wires and IC's and the like. If you have purchased a card that -+provides an external i2c/smbus this will require combined algorithm and -+adapter code in a single module. -+If you are doing it yourself by using the parallel port there -+are basically 2 options. -+ -+1) Using the parallel port and using the i2c-pport adapter module and the -+i2c-algo-bit algorithm module together to enable you to wire up your parallel -+port to act as an i2c/smbus. This provides a bus that will enable most -+sensors to work but doesn't support the entire i2c/smbus capability. -+ -+2) Using the parallel port to interface to a Philips PCF8584 parallel to i2c -+adapter chip. You will need to build a bit of a circuit to do this. This -+configuration needs the i2c-pcf-epp adapter module and the i2c-algo-pcf -+algorithm module. This support almost all of the i2c/smbus capabilities. -+ -+ -+i2c-pport Documentation -+----------------------- -+This is a primitive parallel port driver for the i2c bus, which exploits -+features of modern bidirectional parallel ports. -+ -+Bidirectional ports have particular bits connected in following way: -+ -+ | -+ /-----| R -+ --o| |-----| -+ read \-----| /------- Out pin -+ |/ -+ - -|\ -+ write V -+ | -+ --- -+ -+ -+It means when output is set to 1 we can read the port. Therefore -+we can use 2 pins of parallel port as SDA and SCL for i2c bus. It -+is not necessary to add any external - additional parts, we can -+read and write the same port simultaneously. -+ I only use register base+2 so it is possible to use all -+8 data bits of parallel port for other applications (I have -+connected EEPROM and LCD display). I do not use bit Enable Bi-directional -+ Port. The only disadvantage is we can only support 5V chips. -+ -+Layout: -+ -+Cannon 25 pin -+ -+SDA - connect to pin 14 (Auto Linefeed) -+SCL - connect to pin 16 (Initialize Printer) -+GND - connect to pin 18-25 -++5V - use external supply (I use 5V from 3.5" floppy connector) -+ -+no pullups requied -+ -+Module parameters: -+ -+base = 0xXXX -+XXX - 278 or 378 -+ -+That's all. -+ -+Daniel Smolik -+marvin@sitour.cz ---- linux-old/Documentation/i2c/i2c-protocol Mon Dec 22 22:44:34 2003 -+++ linux/Documentation/i2c/i2c-protocol Mon Dec 13 19:26:24 2004 -@@ -65,3 +65,12 @@ - need to emit an Rd instead of a Wr, or vice versa, you set this - flag. For example: - S Addr Rd [A] Data [A] Data [A] ... [A] Data [A] P -+ -+ Flags I2C_M_IGNORE_NAK -+ Normally message is interrupted immediately if there is [NA] from the -+ client. Setting this flag treats any [NA] as [A], and all of -+ message is sent. -+ These messages may still fail to SCL lo->hi timeout. -+ -+ Flags I2C_M_NO_RD_ACK -+ In a read message, master A/NA bit is skipped. ---- linux-old/Documentation/i2c/summary Tue Jan 20 15:10:28 2004 -+++ linux/Documentation/i2c/summary Mon Dec 13 19:26:24 2004 -@@ -59,16 +59,16 @@ - i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT) - i2c-algo-bit: A bit-banging algorithm - i2c-algo-pcf: A PCF 8584 style algorithm --i2c-algo-ppc405: An algorithm for the I2C device in IBM 405xx processors (NOT BUILT BY DEFAULT) -+i2c-algo-ibm_ocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT) - - Adapter drivers - --------------- - - i2c-elektor: Elektor ISA card (uses i2c-algo-pcf) - i2c-elv: ELV parallel port adapter (uses i2c-algo-bit) --i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (BROKEN - missing i2c-pcf-epp.h) -+i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatched) - i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit) --i2c-ppc405: IBM 405xx processor I2C device (uses i2c-algo-ppc405) (NOT BUILT BY DEFAULT) -+i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT) - i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit) - i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT) - i2c-velleman: Velleman K8000 parallel port adapter (uses i2c-algo-bit) ---- linux-old/Documentation/i2c/writing-clients Mon Dec 22 22:44:34 2003 -+++ linux/Documentation/i2c/writing-clients Mon Dec 13 19:26:25 2004 -@@ -24,24 +24,24 @@ - routines, a client structure specific information like the actual I2C - address. - -- struct i2c_driver foo_driver -- { -- /* name */ "Foo version 2.3 and later driver", -- /* id */ I2C_DRIVERID_FOO, -- /* flags */ I2C_DF_NOTIFY, -- /* attach_adapter */ &foo_attach_adapter, -- /* detach_client */ &foo_detach_client, -- /* command */ &foo_command, /* May be NULL */ -- /* inc_use */ &foo_inc_use, /* May be NULL */ -- /* dec_use */ &foo_dec_use /* May be NULL */ -- } -+static struct i2c_driver foo_driver = { -+ .owner = THIS_MODULE, -+ .name = "Foo version 2.3 driver", -+ .id = I2C_DRIVERID_FOO, /* from i2c-id.h, optional */ -+ .flags = I2C_DF_NOTIFY, -+ .attach_adapter = &foo_attach_adapter, -+ .detach_client = &foo_detach_client, -+ .command = &foo_command /* may be NULL */ -+} - - The name can be chosen freely, and may be upto 40 characters long. Please - use something descriptive here. - --The id should be a unique ID. The range 0xf000 to 0xffff is reserved for --local use, and you can use one of those until you start distributing the --driver. Before you do that, contact the i2c authors to get your own ID(s). -+If used, the id should be a unique ID. The range 0xf000 to 0xffff is -+reserved for local use, and you can use one of those until you start -+distributing the driver, at which time you should contact the i2c authors -+to get your own ID(s). Note that most of the time you don't need an ID -+at all so you can just omit it. - - Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This - means that your driver will be notified when new adapters are found. -@@ -50,43 +50,8 @@ - All other fields are for call-back functions which will be explained - below. - -- --Module usage count --================== -- --If your driver can also be compiled as a module, there are moments at --which the module can not be removed from memory. For example, when you --are doing a lengthy transaction, or when you create a /proc directory, --and some process has entered that directory (this last case is the --main reason why these call-backs were introduced). -- --To increase or decrease the module usage count, you can use the --MOD_{INC,DEC}_USE_COUNT macros. They must be called from the module --which needs to get its usage count changed; that is why each driver --module has to implement its own callback. -- -- void foo_inc_use (struct i2c_client *client) -- { -- #ifdef MODULE -- MOD_INC_USE_COUNT; -- #endif -- } -- -- void foo_dec_use (struct i2c_client *client) -- { -- #ifdef MODULE -- MOD_DEC_USE_COUNT; -- #endif -- } -- --Do not call these call-back functions directly; instead, use one of the --following functions defined in i2c.h: -- void i2c_inc_use_client(struct i2c_client *); -- void i2c_dec_use_client(struct i2c_client *); -- --You should *not* increase the module count just because a device is --detected and a client created. This would make it impossible to remove --an adapter driver! -+There use to be two additional fields in this structure, inc_use et dec_use, -+for module usage count, but these fields were obsoleted and removed. - - - Extra client data ---- linux-old/drivers/i2c/i2c-adap-ibm_ocp.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-adap-ibm_ocp.c Mon Dec 13 19:26:26 2004 -@@ -0,0 +1,346 @@ -+/* -+ ------------------------------------------------------------------------- -+ i2c-adap-ibm_ocp.c i2c-hw access for the IIC peripheral on the IBM PPC 405 -+ ------------------------------------------------------------------------- -+ -+ Ian DaSilva, MontaVista Software, Inc. -+ idasilva@mvista.com or source@mvista.com -+ -+ Copyright 2000 MontaVista Software Inc. -+ -+ Changes made to support the IIC peripheral on the IBM PPC 405 -+ -+ -+ ---------------------------------------------------------------------------- -+ This file was highly leveraged from i2c-elektor.c, which was created -+ by Simon G. Vogl and Hans Berglund: -+ -+ -+ Copyright (C) 1995-97 Simon G. Vogl -+ 1998-99 Hans Berglund -+ -+ With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even -+ 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. -+ ---------------------------------------------------------------------------- -+ -+ History: 01/20/12 - Armin -+ akuster@mvista.com -+ ported up to 2.4.16+ -+ -+ Version 02/03/25 - Armin -+ converted to ocp format -+ removed commented out or #if 0 code -+ -+ TODO: convert to ocp_register -+ add PM hooks -+ -+*/ -+ -+ -+#include <linux/kernel.h> -+#include <linux/ioport.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-ibm_ocp.h> -+#include <asm/irq.h> -+#include <asm/io.h> -+#include <asm/ocp.h> -+ -+/* -+ * This next section is configurable, and it is used to set the number -+ * of i2c controllers in the system. The default number of instances is 1, -+ * however, this should be changed to reflect your system's configuration. -+ */ -+ -+/* -+ * The STB03xxx, with a PPC405 core, has two i2c controllers. -+ */ -+//(sizeof(IIC_ADDR)/sizeof(struct iic_regs)) -+extern iic_t *IIC_ADDR[]; -+static struct iic_ibm iic_ibmocp_adaps[IIC_NUMS][5]; -+ -+static struct i2c_algo_iic_data *iic_ibmocp_data[IIC_NUMS]; -+static struct i2c_adapter *iic_ibmocp_ops[IIC_NUMS]; -+ -+static int i2c_debug=0; -+static wait_queue_head_t iic_wait[IIC_NUMS]; -+static int iic_pending; -+static spinlock_t irq_driver_lock = SPIN_LOCK_UNLOCKED; -+ -+ -+/* ----- global defines ----------------------------------------------- */ -+#define DEB(x) if (i2c_debug>=1) x -+#define DEB2(x) if (i2c_debug>=2) x -+#define DEB3(x) if (i2c_debug>=3) x -+#define DEBE(x) x /* error messages */ -+ -+/* ----- local functions ---------------------------------------------- */ -+ -+// -+// Description: Write a byte to IIC hardware -+// -+static void iic_ibmocp_setbyte(void *data, int ctl, int val) -+{ -+ // writeb resolves to a write to the specified memory location -+ // plus a call to eieio. eieio ensures that all instructions -+ // preceding it are completed before any further stores are -+ // completed. -+ // Delays at this level (to protect writes) are not needed here. -+ writeb(val, ctl); -+} -+ -+ -+// -+// Description: Read a byte from IIC hardware -+// -+static int iic_ibmocp_getbyte(void *data, int ctl) -+{ -+ int val; -+ -+ val = readb(ctl); -+ return (val); -+} -+ -+ -+// -+// Description: Return our slave address. This is the address -+// put on the I2C bus when another master on the bus wants to address us -+// as a slave -+// -+static int iic_ibmocp_getown(void *data) -+{ -+ return(((struct iic_ibm *)(data))->iic_own); -+} -+ -+ -+// -+// Description: Return the clock rate -+// -+static int iic_ibmocp_getclock(void *data) -+{ -+ return(((struct iic_ibm *)(data))->iic_clock); -+} -+ -+ -+ -+// -+// Description: Put this process to sleep. We will wake up when the -+// IIC controller interrupts. -+// -+static void iic_ibmocp_waitforpin(void *data) { -+ -+ int timeout = 2; -+ struct iic_ibm *priv_data = data; -+ -+ // -+ // If interrupts are enabled (which they are), then put the process to -+ // sleep. This process will be awakened by two events -- either the -+ // the IIC peripheral interrupts or the timeout expires. -+ // -+ if (priv_data->iic_irq > 0) { -+ spin_lock_irq(&irq_driver_lock); -+ if (iic_pending == 0) { -+ interruptible_sleep_on_timeout(&(iic_wait[priv_data->index]), timeout*HZ ); -+ } else -+ iic_pending = 0; -+ spin_unlock_irq(&irq_driver_lock); -+ } else { -+ // -+ // If interrupts are not enabled then delay for a reasonable amount -+ // of time and return. We expect that by time we return to the calling -+ // function that the IIC has finished our requested transaction and -+ // the status bit reflects this. -+ // -+ // udelay is probably not the best choice for this since it is -+ // the equivalent of a busy wait -+ // -+ udelay(100); -+ } -+ //printk("iic_ibmocp_waitforpin: exitting\n"); -+} -+ -+ -+// -+// Description: The registered interrupt handler -+// -+static void iic_ibmocp_handler(int this_irq, void *dev_id, struct pt_regs *regs) -+{ -+ int ret; -+ struct iic_regs *iic; -+ struct iic_ibm *priv_data = dev_id; -+ iic = (struct iic_regs *) priv_data->iic_base; -+ iic_pending = 1; -+ DEB2(printk("iic_ibmocp_handler: in interrupt handler\n")); -+ // Read status register -+ ret = readb((int) &(iic->sts)); -+ DEB2(printk("iic_ibmocp_handler: status = %x\n", ret)); -+ // Clear status register. See IBM PPC 405 reference manual for details -+ writeb(0x0a, (int) &(iic->sts)); -+ wake_up_interruptible(&(iic_wait[priv_data->index])); -+} -+ -+ -+// -+// Description: This function is very hardware dependent. First, we lock -+// the region of memory where out registers exist. Next, we request our -+// interrupt line and register its associated handler. Our IIC peripheral -+// uses interrupt number 2, as specified by the 405 reference manual. -+// -+static int iic_hw_resrc_init(int instance) -+{ -+ -+ DEB(printk("iic_hw_resrc_init: Physical Base address: 0x%x\n", (u32) IIC_ADDR[instance] )); -+ iic_ibmocp_adaps[instance]->iic_base = (u32)ioremap((unsigned long)IIC_ADDR[instance],PAGE_SIZE); -+ -+ DEB(printk("iic_hw_resrc_init: ioremapped base address: 0x%x\n", iic_ibmocp_adaps[instance]->iic_base)); -+ -+ if (iic_ibmocp_adaps[instance]->iic_irq > 0) { -+ -+ if (request_irq(iic_ibmocp_adaps[instance]->iic_irq, iic_ibmocp_handler, -+ 0, "IBM OCP IIC", iic_ibmocp_adaps[instance]) < 0) { -+ printk(KERN_ERR "iic_hw_resrc_init: Request irq%d failed\n", -+ iic_ibmocp_adaps[instance]->iic_irq); -+ iic_ibmocp_adaps[instance]->iic_irq = 0; -+ } else { -+ DEB3(printk("iic_hw_resrc_init: Enabled interrupt\n")); -+ } -+ } -+ return 0; -+} -+ -+ -+// -+// Description: Release irq and memory -+// -+static void iic_ibmocp_release(void) -+{ -+ int i; -+ -+ for(i=0; i<IIC_NUMS; i++) { -+ struct iic_ibm *priv_data = (struct iic_ibm *)iic_ibmocp_data[i]->data; -+ if (priv_data->iic_irq > 0) { -+ disable_irq(priv_data->iic_irq); -+ free_irq(priv_data->iic_irq, 0); -+ } -+ kfree(iic_ibmocp_data[i]); -+ kfree(iic_ibmocp_ops[i]); -+ } -+} -+ -+ -+// -+// Description: Called when the module is loaded. This function starts the -+// cascade of calls up through the heirarchy of i2c modules (i.e. up to the -+// algorithm layer and into to the core layer) -+// -+static int __init iic_ibmocp_init(void) -+{ -+ int i; -+ -+ printk(KERN_INFO "iic_ibmocp_init: IBM on-chip iic adapter module\n"); -+ -+ for(i=0; i<IIC_NUMS; i++) { -+ iic_ibmocp_data[i] = kmalloc(sizeof(struct i2c_algo_iic_data),GFP_KERNEL); -+ if(iic_ibmocp_data[i] == NULL) { -+ return -ENOMEM; -+ } -+ memset(iic_ibmocp_data[i], 0, sizeof(struct i2c_algo_iic_data)); -+ -+ switch (i) { -+ case 0: -+ iic_ibmocp_adaps[i]->iic_irq = IIC_IRQ(0); -+ break; -+ case 1: -+ iic_ibmocp_adaps[i]->iic_irq = IIC_IRQ(1); -+ break; -+ } -+ iic_ibmocp_adaps[i]->iic_clock = IIC_CLOCK; -+ iic_ibmocp_adaps[i]->iic_own = IIC_OWN; -+ iic_ibmocp_adaps[i]->index = i; -+ -+ DEB(printk("irq %x\n", iic_ibmocp_adaps[i]->iic_irq)); -+ DEB(printk("clock %x\n", iic_ibmocp_adaps[i]->iic_clock)); -+ DEB(printk("own %x\n", iic_ibmocp_adaps[i]->iic_own)); -+ DEB(printk("index %x\n", iic_ibmocp_adaps[i]->index)); -+ -+ -+ iic_ibmocp_data[i]->data = (struct iic_regs *)iic_ibmocp_adaps[i]; -+ iic_ibmocp_data[i]->setiic = iic_ibmocp_setbyte; -+ iic_ibmocp_data[i]->getiic = iic_ibmocp_getbyte; -+ iic_ibmocp_data[i]->getown = iic_ibmocp_getown; -+ iic_ibmocp_data[i]->getclock = iic_ibmocp_getclock; -+ iic_ibmocp_data[i]->waitforpin = iic_ibmocp_waitforpin; -+ iic_ibmocp_data[i]->udelay = 80; -+ iic_ibmocp_data[i]->mdelay = 80; -+ iic_ibmocp_data[i]->timeout = HZ; -+ -+ iic_ibmocp_ops[i] = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL); -+ if(iic_ibmocp_ops[i] == NULL) { -+ return -ENOMEM; -+ } -+ memset(iic_ibmocp_ops[i], 0, sizeof(struct i2c_adapter)); -+ strcpy(iic_ibmocp_ops[i]->name, "IBM OCP IIC adapter"); -+ iic_ibmocp_ops[i]->owner = THIS_MODULE; -+ iic_ibmocp_ops[i]->id = I2C_HW_OCP; -+ iic_ibmocp_ops[i]->algo = NULL; -+ iic_ibmocp_ops[i]->algo_data = iic_ibmocp_data[i]; -+ -+ -+ init_waitqueue_head(&(iic_wait[i])); -+ if (iic_hw_resrc_init(i) == 0) { -+ if (i2c_ocp_add_bus(iic_ibmocp_ops[i]) < 0) -+ return -ENODEV; -+ } else { -+ return -ENODEV; -+ } -+ DEB(printk(KERN_INFO "iic_ibmocp_init: found device at %#x.\n\n", iic_ibmocp_adaps[i]->iic_base)); -+ } -+ return 0; -+} -+ -+ -+static void __exit iic_ibmocp_exit(void) -+{ -+ int i; -+ -+ for(i=0; i<IIC_NUMS; i++) { -+ i2c_ocp_del_bus(iic_ibmocp_ops[i]); -+ } -+ iic_ibmocp_release(); -+} -+ -+// -+// If modules is NOT defined when this file is compiled, then the MODULE_* -+// macros will resolve to nothing -+// -+MODULE_AUTHOR("MontaVista Software <www.mvista.com>"); -+MODULE_DESCRIPTION("I2C-Bus adapter routines for PPC 405 IIC bus adapter"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(base, "i"); -+MODULE_PARM(irq, "i"); -+MODULE_PARM(clock, "i"); -+MODULE_PARM(own, "i"); -+MODULE_PARM(i2c_debug,"i"); -+ -+ -+module_init(iic_ibmocp_init); -+module_exit(iic_ibmocp_exit); ---- linux-old/drivers/i2c/i2c-algo-8xx.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-algo-8xx.c Mon Dec 13 19:26:27 2004 -@@ -0,0 +1,616 @@ -+/* -+ * i2c-algo-8xx.c i2x driver algorithms for MPC8XX CPM -+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). -+ * -+ 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. -+ * -+ * moved into proper i2c interface; separated out platform specific -+ * parts into i2c-rpx.c -+ * Brad Parker (brad@heeltoe.com) -+ */ -+ -+// XXX todo -+// timeout sleep? -+ -+/* $Id: i2c-algo-8xx.c,v 1.14 2003/07/25 07:56:42 khali Exp $ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/errno.h> -+#include <linux/sched.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-8xx.h> -+#include <asm/mpc8xx.h> -+#include <asm/commproc.h> -+ -+ -+#define CPM_MAX_READ 513 -+/* #define I2C_CHIP_ERRATA */ /* Try uncomment this if you have an older CPU(earlier than rev D4) */ -+static wait_queue_head_t iic_wait; -+static ushort r_tbase, r_rbase; -+ -+int cpm_debug = 0; -+ -+static void -+cpm_iic_interrupt(void *dev_id, struct pt_regs *regs) -+{ -+ volatile i2c8xx_t *i2c = (i2c8xx_t *)dev_id; -+ if (cpm_debug > 1) -+ printk("cpm_iic_interrupt(dev_id=%p)\n", dev_id); -+#if 0 -+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs */ -+ /* This should probably be removed and replaced by I2C_CHIP_ERRATA stuff */ -+ /* Someone with a buggy CPU needs to confirm that */ -+ i2c->i2c_i2mod &= ~1; -+#endif -+ /* Clear interrupt. -+ */ -+ i2c->i2c_i2cer = 0xff; -+ -+ /* Get 'me going again. -+ */ -+ wake_up_interruptible(&iic_wait); -+} -+ -+static void -+cpm_iic_init(struct i2c_algo_8xx_data *cpm) -+{ -+ volatile iic_t *iip = cpm->iip; -+ volatile i2c8xx_t *i2c = cpm->i2c; -+ unsigned char brg; -+ bd_t *bd = (bd_t *)__res; -+ -+ if (cpm_debug) printk(KERN_DEBUG "cpm_iic_init()\n"); -+ -+ /* Initialize the parameter ram. -+ * We need to make sure many things are initialized to zero, -+ * especially in the case of a microcode patch. -+ */ -+ iip->iic_rstate = 0; -+ iip->iic_rdp = 0; -+ iip->iic_rbptr = 0; -+ iip->iic_rbc = 0; -+ iip->iic_rxtmp = 0; -+ iip->iic_tstate = 0; -+ iip->iic_tdp = 0; -+ iip->iic_tbptr = 0; -+ iip->iic_tbc = 0; -+ iip->iic_txtmp = 0; -+ -+ /* Set up the IIC parameters in the parameter ram. -+ */ -+ iip->iic_tbase = r_tbase = cpm->dp_addr; -+ iip->iic_rbase = r_rbase = cpm->dp_addr + sizeof(cbd_t)*2; -+ -+ iip->iic_tfcr = SMC_EB; -+ iip->iic_rfcr = SMC_EB; -+ -+ /* Set maximum receive size. -+ */ -+ iip->iic_mrblr = CPM_MAX_READ; -+ -+ /* Initialize Tx/Rx parameters. -+ */ -+ if (cpm->reloc == 0) { -+ volatile cpm8xx_t *cp = cpm->cp; -+ -+ cp->cp_cpcr = -+ mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG; -+ while (cp->cp_cpcr & CPM_CR_FLG); -+ } else { -+ iip->iic_rbptr = iip->iic_rbase; -+ iip->iic_tbptr = iip->iic_tbase; -+ iip->iic_rstate = 0; -+ iip->iic_tstate = 0; -+ } -+ -+ /* Select an arbitrary address. Just make sure it is unique. -+ */ -+ i2c->i2c_i2add = 0xfe; -+ -+ /* Make clock run at 60 KHz. -+ */ -+ brg = (unsigned char) (bd->bi_intfreq/(32*2*60000) -3); -+ i2c->i2c_i2brg = brg; -+ -+ i2c->i2c_i2mod = 0x00; -+ i2c->i2c_i2com = 0x01; /* Master mode */ -+ -+ /* Disable interrupts. -+ */ -+ i2c->i2c_i2cmr = 0; -+ i2c->i2c_i2cer = 0xff; -+ -+ init_waitqueue_head(&iic_wait); -+ -+ /* Install interrupt handler. -+ */ -+ if (cpm_debug) { -+ printk ("%s[%d] Install ISR for IRQ %d\n", -+ __func__,__LINE__, CPMVEC_I2C); -+ } -+ (*cpm->setisr)(CPMVEC_I2C, cpm_iic_interrupt, (void *)i2c); -+} -+ -+ -+static int -+cpm_iic_shutdown(struct i2c_algo_8xx_data *cpm) -+{ -+ volatile i2c8xx_t *i2c = cpm->i2c; -+ -+ /* Shut down IIC. -+ */ -+ i2c->i2c_i2mod &= ~1; -+ i2c->i2c_i2cmr = 0; -+ i2c->i2c_i2cer = 0xff; -+ -+ return(0); -+} -+ -+static void -+cpm_reset_iic_params(volatile iic_t *iip) -+{ -+ iip->iic_tbase = r_tbase; -+ iip->iic_rbase = r_rbase; -+ -+ iip->iic_tfcr = SMC_EB; -+ iip->iic_rfcr = SMC_EB; -+ -+ iip->iic_mrblr = CPM_MAX_READ; -+ -+ iip->iic_rstate = 0; -+ iip->iic_rdp = 0; -+ iip->iic_rbptr = iip->iic_rbase; -+ iip->iic_rbc = 0; -+ iip->iic_rxtmp = 0; -+ iip->iic_tstate = 0; -+ iip->iic_tdp = 0; -+ iip->iic_tbptr = iip->iic_tbase; -+ iip->iic_tbc = 0; -+ iip->iic_txtmp = 0; -+} -+ -+#define BD_SC_NAK ((ushort)0x0004) /* NAK - did not respond */ -+#define BD_SC_OV ((ushort)0x0002) /* OV - receive overrun */ -+#define CPM_CR_CLOSE_RXBD ((ushort)0x0007) -+ -+static void force_close(struct i2c_algo_8xx_data *cpm) -+{ -+ volatile i2c8xx_t *i2c = cpm->i2c; -+ if (cpm->reloc == 0) { /* micro code disabled */ -+ volatile cpm8xx_t *cp = cpm->cp; -+ -+ if (cpm_debug) printk("force_close()\n"); -+ cp->cp_cpcr = -+ mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) | -+ CPM_CR_FLG; -+ -+ while (cp->cp_cpcr & CPM_CR_FLG); -+ } -+ i2c->i2c_i2cmr = 0x00; /* Disable all interrupts */ -+ i2c->i2c_i2cer = 0xff; -+} -+ -+ -+/* Read from IIC... -+ * abyte = address byte, with r/w flag already set -+ */ -+static int -+cpm_iic_read(struct i2c_algo_8xx_data *cpm, u_char abyte, char *buf, int count) -+{ -+ volatile iic_t *iip = cpm->iip; -+ volatile i2c8xx_t *i2c = cpm->i2c; -+ volatile cpm8xx_t *cp = cpm->cp; -+ volatile cbd_t *tbdf, *rbdf; -+ u_char *tb; -+ unsigned long flags, tmo; -+ -+ if (count >= CPM_MAX_READ) -+ return -EINVAL; -+ -+ /* check for and use a microcode relocation patch */ -+ if (cpm->reloc) { -+ cpm_reset_iic_params(iip); -+ } -+ -+ tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase]; -+ rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase]; -+ -+ /* To read, we need an empty buffer of the proper length. -+ * All that is used is the first byte for address, the remainder -+ * is just used for timing (and doesn't really have to exist). -+ */ -+ tb = cpm->temp; -+ tb = (u_char *)(((uint)tb + 15) & ~15); -+ tb[0] = abyte; /* Device address byte w/rw flag */ -+ -+ flush_dcache_range((unsigned long) tb, (unsigned long) (tb+1)); -+ -+ if (cpm_debug) printk("cpm_iic_read(abyte=0x%x)\n", abyte); -+ -+ tbdf->cbd_bufaddr = __pa(tb); -+ tbdf->cbd_datlen = count + 1; -+ tbdf->cbd_sc = -+ BD_SC_READY | BD_SC_LAST | -+ BD_SC_WRAP | BD_IIC_START; -+ -+ iip->iic_mrblr = count +1; /* prevent excessive read, +1 -+ is needed otherwise will the -+ RXB interrupt come too early */ -+ -+ /* flush will invalidate too. */ -+ flush_dcache_range((unsigned long) buf, (unsigned long) (buf+count)); -+ -+ rbdf->cbd_datlen = 0; -+ rbdf->cbd_bufaddr = __pa(buf); -+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP| BD_SC_INTRPT; -+ if(count > 16){ -+ /* Chip bug, set enable here */ -+ local_irq_save(flags); -+ i2c->i2c_i2cmr = 0x13; /* Enable some interupts */ -+ i2c->i2c_i2cer = 0xff; -+ i2c->i2c_i2mod |= 1; /* Enable */ -+ i2c->i2c_i2com |= 0x80; /* Begin transmission */ -+ -+ /* Wait for IIC transfer */ -+ tmo = interruptible_sleep_on_timeout(&iic_wait,1*HZ); -+ local_irq_restore(flags); -+ } else { /* busy wait for small transfers, its faster */ -+ i2c->i2c_i2cmr = 0x00; /* Disable I2C interupts */ -+ i2c->i2c_i2cer = 0xff; -+ i2c->i2c_i2mod |= 1; /* Enable */ -+ i2c->i2c_i2com |= 0x80; /* Begin transmission */ -+ tmo = jiffies + 1*HZ; -+ while(!(i2c->i2c_i2cer & 0x11 || time_after(jiffies, tmo))); /* Busy wait, with a timeout */ -+ } -+ -+ if (signal_pending(current) || !tmo){ -+ force_close(cpm); -+ if(cpm_debug) -+ printk("IIC read: timeout!\n"); -+ return -EIO; -+ } -+#ifdef I2C_CHIP_ERRATA -+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs. -+ Disabling I2C too early may cause too short stop condition */ -+ udelay(4); -+ i2c->i2c_i2mod &= ~1; -+#endif -+ if (cpm_debug) { -+ printk("tx sc %04x, rx sc %04x\n", -+ tbdf->cbd_sc, rbdf->cbd_sc); -+ } -+ -+ if (tbdf->cbd_sc & BD_SC_READY) { -+ printk("IIC read; complete but tbuf ready\n"); -+ force_close(cpm); -+ printk("tx sc %04x, rx sc %04x\n", -+ tbdf->cbd_sc, rbdf->cbd_sc); -+ } -+ -+ if (tbdf->cbd_sc & BD_SC_NAK) { -+ if (cpm_debug) -+ printk("IIC read; no ack\n"); -+ return -EREMOTEIO; -+ } -+ -+ if (rbdf->cbd_sc & BD_SC_EMPTY) { -+ /* force_close(cpm); */ -+ if (cpm_debug){ -+ printk("IIC read; complete but rbuf empty\n"); -+ printk("tx sc %04x, rx sc %04x\n", -+ tbdf->cbd_sc, rbdf->cbd_sc); -+ } -+ return -EREMOTEIO; -+ } -+ -+ if (rbdf->cbd_sc & BD_SC_OV) { -+ if (cpm_debug) -+ printk("IIC read; Overrun\n"); -+ return -EREMOTEIO;; -+ } -+ -+ if (cpm_debug) printk("read %d bytes\n", rbdf->cbd_datlen); -+ -+ if (rbdf->cbd_datlen < count) { -+ if (cpm_debug) -+ printk("IIC read; short, wanted %d got %d\n", -+ count, rbdf->cbd_datlen); -+ return 0; -+ } -+ -+ return count; -+} -+ -+/* Write to IIC... -+ * addr = address byte, with r/w flag already set -+ */ -+static int -+cpm_iic_write(struct i2c_algo_8xx_data *cpm, u_char abyte, char *buf,int count) -+{ -+ volatile iic_t *iip = cpm->iip; -+ volatile i2c8xx_t *i2c = cpm->i2c; -+ volatile cpm8xx_t *cp = cpm->cp; -+ volatile cbd_t *tbdf; -+ u_char *tb; -+ unsigned long flags, tmo; -+ -+ /* check for and use a microcode relocation patch */ -+ if (cpm->reloc) { -+ cpm_reset_iic_params(iip); -+ } -+ tb = cpm->temp; -+ tb = (u_char *)(((uint)tb + 15) & ~15); -+ *tb = abyte; /* Device address byte w/rw flag */ -+ -+ flush_dcache_range((unsigned long) tb, (unsigned long) (tb+1)); -+ flush_dcache_range((unsigned long) buf, (unsigned long) (buf+count)); -+ -+ if (cpm_debug) printk("cpm_iic_write(abyte=0x%x)\n", abyte); -+ -+ /* set up 2 descriptors */ -+ tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase]; -+ -+ tbdf[0].cbd_bufaddr = __pa(tb); -+ tbdf[0].cbd_datlen = 1; -+ tbdf[0].cbd_sc = BD_SC_READY | BD_IIC_START; -+ -+ tbdf[1].cbd_bufaddr = __pa(buf); -+ tbdf[1].cbd_datlen = count; -+ tbdf[1].cbd_sc = BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST | BD_SC_WRAP; -+ -+ if(count > 16){ -+ /* Chip bug, set enable here */ -+ local_irq_save(flags); -+ i2c->i2c_i2cmr = 0x13; /* Enable some interupts */ -+ i2c->i2c_i2cer = 0xff; -+ i2c->i2c_i2mod |= 1; /* Enable */ -+ i2c->i2c_i2com |= 0x80; /* Begin transmission */ -+ -+ /* Wait for IIC transfer */ -+ tmo = interruptible_sleep_on_timeout(&iic_wait,1*HZ); -+ local_irq_restore(flags); -+ } else { /* busy wait for small transfers, its faster */ -+ i2c->i2c_i2cmr = 0x00; /* Disable I2C interupts */ -+ i2c->i2c_i2cer = 0xff; -+ i2c->i2c_i2mod |= 1; /* Enable */ -+ i2c->i2c_i2com |= 0x80; /* Begin transmission */ -+ tmo = jiffies + 1*HZ; -+ while(!(i2c->i2c_i2cer & 0x12 || time_after(jiffies, tmo))); /* Busy wait, with a timeout */ -+ } -+ -+ if (signal_pending(current) || !tmo){ -+ force_close(cpm); -+ if(cpm_debug && !tmo) -+ printk("IIC write: timeout!\n"); -+ return -EIO; -+ } -+ -+#if I2C_CHIP_ERRATA -+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs. -+ Disabling I2C too early may cause too short stop condition */ -+ udelay(4); -+ i2c->i2c_i2mod &= ~1; -+#endif -+ if (cpm_debug) { -+ printk("tx0 sc %04x, tx1 sc %04x\n", -+ tbdf[0].cbd_sc, tbdf[1].cbd_sc); -+ } -+ -+ if (tbdf->cbd_sc & BD_SC_NAK) { -+ if (cpm_debug) -+ printk("IIC write; no ack\n"); -+ return 0; -+ } -+ -+ if (tbdf->cbd_sc & BD_SC_READY) { -+ if (cpm_debug) -+ printk("IIC write; complete but tbuf ready\n"); -+ return 0; -+ } -+ -+ return count; -+} -+ -+/* See if an IIC address exists.. -+ * addr = 7 bit address, unshifted -+ */ -+static int -+cpm_iic_tryaddress(struct i2c_algo_8xx_data *cpm, int addr) -+{ -+ volatile iic_t *iip = cpm->iip; -+ volatile i2c8xx_t *i2c = cpm->i2c; -+ volatile cpm8xx_t *cp = cpm->cp; -+ volatile cbd_t *tbdf, *rbdf; -+ u_char *tb; -+ unsigned long flags, len, tmo; -+ -+ if (cpm_debug > 1) -+ printk("cpm_iic_tryaddress(cpm=%p,addr=%d)\n", cpm, addr); -+ -+ /* check for and use a microcode relocation patch */ -+ if (cpm->reloc) { -+ cpm_reset_iic_params(iip); -+ } -+ -+ if (cpm_debug && addr == 0) { -+ printk("iip %p, dp_addr 0x%x\n", cpm->iip, cpm->dp_addr); -+ printk("iic_tbase %d, r_tbase %d\n", iip->iic_tbase, r_tbase); -+ } -+ -+ tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase]; -+ rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase]; -+ -+ tb = cpm->temp; -+ tb = (u_char *)(((uint)tb + 15) & ~15); -+ -+ /* do a simple read */ -+ tb[0] = (addr << 1) | 1; /* device address (+ read) */ -+ len = 2; -+ -+ flush_dcache_range((unsigned long) tb, (unsigned long) (tb+2)); -+ -+ tbdf->cbd_bufaddr = __pa(tb); -+ tbdf->cbd_datlen = len; -+ tbdf->cbd_sc = -+ BD_SC_READY | BD_SC_LAST | -+ BD_SC_WRAP | BD_IIC_START; -+ -+ rbdf->cbd_datlen = 0; -+ rbdf->cbd_bufaddr = __pa(tb+2); -+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT; -+ -+ local_irq_save(flags); -+ i2c->i2c_i2cmr = 0x13; /* Enable some interupts */ -+ i2c->i2c_i2cer = 0xff; -+ i2c->i2c_i2mod |= 1; /* Enable */ -+ i2c->i2c_i2com |= 0x80; /* Begin transmission */ -+ -+ if (cpm_debug > 1) printk("about to sleep\n"); -+ -+ /* wait for IIC transfer */ -+ tmo = interruptible_sleep_on_timeout(&iic_wait,1*HZ); -+ local_irq_restore(flags); -+ -+#ifdef I2C_CHIP_ERRATA -+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs. -+ Disabling I2C too early may cause too short stop condition */ -+ udelay(4); -+ i2c->i2c_i2mod &= ~1; -+#endif -+ -+ if (signal_pending(current) || !tmo){ -+ force_close(cpm); -+ if(cpm_debug && !tmo) -+ printk("IIC tryaddress: timeout!\n"); -+ return -EIO; -+ } -+ -+ if (cpm_debug > 1) printk("back from sleep\n"); -+ -+ if (tbdf->cbd_sc & BD_SC_NAK) { -+ if (cpm_debug > 1) printk("IIC try; no ack\n"); -+ return 0; -+ } -+ -+ if (tbdf->cbd_sc & BD_SC_READY) { -+ printk("IIC try; complete but tbuf ready\n"); -+ } -+ -+ return 1; -+} -+ -+static int cpm_xfer(struct i2c_adapter *adap, -+ struct i2c_msg msgs[], -+ int num) -+{ -+ struct i2c_algo_8xx_data *cpm = adap->algo_data; -+ struct i2c_msg *pmsg; -+ int i, ret; -+ u_char addr; -+ -+ for (i = 0; i < num; i++) { -+ pmsg = &msgs[i]; -+ -+ if (cpm_debug) -+ printk("i2c-algo-8xx.o: " -+ "#%d addr=0x%x flags=0x%x len=%d\n buf=%lx\n", -+ i, pmsg->addr, pmsg->flags, pmsg->len, (unsigned long)pmsg->buf); -+ -+ addr = pmsg->addr << 1; -+ if (pmsg->flags & I2C_M_RD ) -+ addr |= 1; -+ if (pmsg->flags & I2C_M_REV_DIR_ADDR ) -+ addr ^= 1; -+ -+ if (!(pmsg->flags & I2C_M_NOSTART)) { -+ } -+ if (pmsg->flags & I2C_M_RD ) { -+ /* read bytes into buffer*/ -+ ret = cpm_iic_read(cpm, addr, pmsg->buf, pmsg->len); -+ if (cpm_debug) -+ printk("i2c-algo-8xx.o: read %d bytes\n", ret); -+ if (ret < pmsg->len ) { -+ return (ret<0)? ret : -EREMOTEIO; -+ } -+ } else { -+ /* write bytes from buffer */ -+ ret = cpm_iic_write(cpm, addr, pmsg->buf, pmsg->len); -+ if (cpm_debug) -+ printk("i2c-algo-8xx.o: wrote %d\n", ret); -+ if (ret < pmsg->len ) { -+ return (ret<0) ? ret : -EREMOTEIO; -+ } -+ } -+ } -+ return (num); -+} -+ -+static u32 cpm_func(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | -+ I2C_FUNC_PROTOCOL_MANGLING; -+} -+ -+/* -----exported algorithm data: ------------------------------------- */ -+ -+static struct i2c_algorithm cpm_algo = { -+ .owner = THIS_MODULE, -+ .name = "MPC8xx CPM algorithm", -+ .id = I2C_ALGO_MPC8XX, -+ .master_xfer = cpm_xfer, -+ .functionality = cpm_func, -+}; -+ -+/* -+ * registering functions to load algorithms at runtime -+ */ -+int i2c_8xx_add_bus(struct i2c_adapter *adap) -+{ -+ int i; -+ struct i2c_algo_8xx_data *cpm = adap->algo_data; -+ -+ if (cpm_debug) -+ printk("i2c-algo-8xx.o: hw routines for %s registered.\n", -+ adap->name); -+ -+ /* register new adapter to i2c module... */ -+ -+ adap->id |= cpm_algo.id; -+ adap->algo = &cpm_algo; -+ -+ i2c_add_adapter(adap); -+ cpm_iic_init(cpm); -+} -+ -+ -+int i2c_8xx_del_bus(struct i2c_adapter *adap) -+{ -+ struct i2c_algo_8xx_data *cpm = adap->algo_data; -+ -+ cpm_iic_shutdown(cpm); -+ -+ return i2c_del_adapter(adap); -+} -+ -+EXPORT_SYMBOL(i2c_8xx_add_bus); -+EXPORT_SYMBOL(i2c_8xx_del_bus); -+ -+MODULE_AUTHOR("Brad Parker <brad@heeltoe.com>"); -+MODULE_DESCRIPTION("I2C-Bus MPC8XX algorithm"); -+MODULE_LICENSE("GPL"); ---- linux-old/include/linux/i2c-algo-8xx.h Thu Jan 1 00:00:00 1970 -+++ linux/include/linux/i2c-algo-8xx.h Mon Dec 13 19:26:27 2004 -@@ -0,0 +1,43 @@ -+/* ------------------------------------------------------------------------- */ -+/* i2c-algo-8xx.h i2c driver algorithms for MPX8XX CPM */ -+/* -+ 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: i2c-algo-8xx.h,v 1.7 2003/08/01 20:56:38 khali Exp $ */ -+ -+#ifndef _LINUX_I2C_ALGO_8XX_H -+#define _LINUX_I2C_ALGO_8XX_H -+ -+#include "asm/commproc.h" -+ -+struct i2c_algo_8xx_data { -+ uint dp_addr; -+ int reloc; -+ volatile i2c8xx_t *i2c; -+ volatile iic_t *iip; -+ volatile cpm8xx_t *cp; -+ -+ int (*setisr) (int irq, -+ void (*func)(void *, void *), -+ void *data); -+ -+ u_char temp[513]; -+}; -+ -+int i2c_8xx_add_bus(struct i2c_adapter *); -+int i2c_8xx_del_bus(struct i2c_adapter *); -+ -+#endif /* _LINUX_I2C_ALGO_8XX_H */ ---- linux-old/drivers/i2c/i2c-algo-bit.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-algo-bit.c Mon Dec 13 19:26:27 2004 -@@ -18,24 +18,22 @@ - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* ------------------------------------------------------------------------- */ - --/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even -- Frodo Looijaard <frodol@dds.nl> */ -+/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki -+ <kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */ - --/* $Id: i2c-algo-bit.c,v 1.30 2001/07/29 02:44:25 mds Exp $ */ -+/* $Id: i2c-algo-bit.c,v 1.50 2003/12/22 20:03:39 khali Exp $ */ - - #include <linux/kernel.h> - #include <linux/module.h> - #include <linux/delay.h> - #include <linux/slab.h> - #include <linux/init.h> --#include <asm/uaccess.h> --#include <linux/ioport.h> - #include <linux/errno.h> - #include <linux/sched.h> -- - #include <linux/i2c.h> - #include <linux/i2c-algo-bit.h> - -+ - /* ----- global defines ----------------------------------------------- */ - #define DEB(x) if (i2c_debug>=1) x; - #define DEB2(x) if (i2c_debug>=2) x; -@@ -43,27 +41,13 @@ - #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 */ --/* --#define SLO_IO jif=jiffies;while(time_before_eq(jiffies, jif+i2c_table[minor].veryslow))\ -- if (need_resched) schedule(); --*/ -- - - /* ----- global variables --------------------------------------------- */ - --#ifdef SLO_IO -- int jif; --#endif -- - /* module parameters: - */ - static int i2c_debug; - static int bit_test; /* see if the line-setting functions work */ --static int bit_scan; /* have a look at what's hanging 'round */ - - /* --- setting states on the bus with the right timing: --------------- */ - -@@ -88,9 +72,6 @@ - { - setscl(adap,0); - udelay(adap->udelay); --#ifdef SLO_IO -- SLO_IO --#endif - } - - /* -@@ -99,33 +80,35 @@ - */ - static inline int sclhi(struct i2c_algo_bit_data *adap) - { -- int start=jiffies; -+ int start; - - setscl(adap,1); - -- udelay(adap->udelay); -- - /* Not all adapters have scl sense line... */ -- if (adap->getscl == NULL ) -+ if (adap->getscl == NULL ) { -+ udelay(adap->udelay); - return 0; -+ } - -- while (! getscl(adap) ) { -+ start=jiffies; -+ 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 (time_after_eq(jiffies, start+adap->timeout)) { - return -ETIMEDOUT; - } -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - if (current->need_resched) - schedule(); -+#else -+ cond_resched(); -+#endif - } - DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start)); --#ifdef SLO_IO -- SLO_IO --#endif -+ udelay(adap->udelay); - return 0; - } - -@@ -144,7 +127,7 @@ - /* scl, sda may not be high */ - DEBPROTO(printk(" Sr ")); - setsda(adap,1); -- setscl(adap,1); -+ sclhi(adap); - udelay(adap->udelay); - - sdalo(adap); -@@ -178,7 +161,6 @@ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - /* assert: scl is low */ -- DEB2(printk(KERN_DEBUG " i2c_outb:%2.2X\n",c&0xff)); - for ( i=7 ; i>=0 ; i-- ) { - sb = c & ( 1 << i ); - setsda(adap,sb); -@@ -186,6 +168,7 @@ - DEBPROTO(printk(KERN_DEBUG "%d",sb!=0)); - if (sclhi(adap)<0) { /* timed out */ - sdahi(adap); /* we don't want to block the net */ -+ DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i)); - return -ETIMEDOUT; - }; - /* do arbitration here: -@@ -196,11 +179,12 @@ - } - sdahi(adap); - if (sclhi(adap)<0){ /* timeout */ -+ DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff)); - return -ETIMEDOUT; - }; - /* read ack: SDA should be pulled down by slave */ - ack=getsda(adap); /* ack: sda is pulled low ->success. */ -- DEB2(printk(KERN_DEBUG " i2c_outb: getsda() = 0x%2.2x\n", ~ack )); -+ DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack)); - - DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) ); - DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") ); -@@ -219,11 +203,10 @@ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - /* assert: scl is low */ -- DEB2(printk(KERN_DEBUG "i2c_inb.\n")); -- - sdahi(adap); - for (i=0;i<8;i++) { - if (sclhi(adap)<0) { /* timeout */ -+ DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i)); - return -ETIMEDOUT; - }; - indata *= 2; -@@ -232,6 +215,8 @@ - scllo(adap); - } - /* assert: scl is low */ -+ DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff)); -+ - DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff)); - return (int) (indata & 0xff); - } -@@ -242,71 +227,75 @@ - */ - static int test_bus(struct i2c_algo_bit_data *adap, char* name) { - int scl,sda; -+ -+ if (adap->getscl==NULL) -+ printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, " -+ "SCL is not readable.\n"); -+ - sda=getsda(adap); -- if (adap->getscl==NULL) { -- printk("i2c-algo-bit.o: Warning: Adapter can't read from clock line - skipping test.\n"); -- return 0; -- } -- scl=getscl(adap); -- printk("i2c-algo-bit.o: Adapter: %s scl: %d sda: %d -- testing...\n", -- name,getscl(adap),getsda(adap)); -+ scl=(adap->getscl==NULL?1:getscl(adap)); -+ printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda); - if (!scl || !sda ) { -- printk("i2c-algo-bit.o: %s seems to be busy.\n",name); -+ printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name); - goto bailout; - } -+ - sdalo(adap); -- printk("i2c-algo-bit.o:1 scl: %d sda: %d \n",getscl(adap), -- getsda(adap)); -- if ( 0 != getsda(adap) ) { -- printk("i2c-algo-bit.o: %s SDA stuck high!\n",name); -- sdahi(adap); -+ sda=getsda(adap); -+ scl=(adap->getscl==NULL?1:getscl(adap)); -+ printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda); -+ if ( 0 != sda ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n"); - goto bailout; - } -- if ( 0 == getscl(adap) ) { -- printk("i2c-algo-bit.o: %s SCL unexpected low while pulling SDA low!\n", -- name); -+ if ( 0 == scl ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low " -+ "while pulling SDA low!\n"); - goto bailout; - } -+ - sdahi(adap); -- printk("i2c-algo-bit.o:2 scl: %d sda: %d \n",getscl(adap), -- getsda(adap)); -- if ( 0 == getsda(adap) ) { -- printk("i2c-algo-bit.o: %s SDA stuck low!\n",name); -- sdahi(adap); -+ sda=getsda(adap); -+ scl=(adap->getscl==NULL?1:getscl(adap)); -+ printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda); -+ if ( 0 == sda ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n"); - goto bailout; - } -- if ( 0 == getscl(adap) ) { -- printk("i2c-algo-bit.o: %s SCL unexpected low while SDA high!\n", -- name); -- goto bailout; -+ if ( 0 == scl ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low " -+ "while pulling SDA high!\n"); -+ goto bailout; - } -+ - scllo(adap); -- printk("i2c-algo-bit.o:3 scl: %d sda: %d \n",getscl(adap), -- getsda(adap)); -- if ( 0 != getscl(adap) ) { -- printk("i2c-algo-bit.o: %s SCL stuck high!\n",name); -- sclhi(adap); -+ sda=getsda(adap); -+ scl=(adap->getscl==NULL?0:getscl(adap)); -+ printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda); -+ if ( 0 != scl ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n"); - goto bailout; - } -- if ( 0 == getsda(adap) ) { -- printk("i2c-algo-bit.o: %s SDA unexpected low while pulling SCL low!\n", -- name); -+ if ( 0 == sda ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low " -+ "while pulling SCL low!\n"); - goto bailout; - } -+ - sclhi(adap); -- printk("i2c-algo-bit.o:4 scl: %d sda: %d \n",getscl(adap), -- getsda(adap)); -- if ( 0 == getscl(adap) ) { -- printk("i2c-algo-bit.o: %s SCL stuck low!\n",name); -- sclhi(adap); -+ sda=getsda(adap); -+ scl=(adap->getscl==NULL?1:getscl(adap)); -+ printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda); -+ if ( 0 == scl ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n"); - goto bailout; - } -- if ( 0 == getsda(adap) ) { -- printk("i2c-algo-bit.o: %s SDA unexpected low while SCL high!\n", -- name); -+ if ( 0 == sda ) { -+ printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low " -+ "while pulling SCL high!\n"); - goto bailout; - } -- printk("i2c-algo-bit.o: %s passed test.\n",name); -+ printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name); - return 0; - bailout: - sdahi(adap); -@@ -340,16 +329,21 @@ - i2c_start(adap); - udelay(adap->udelay); - } -- DEB2(if (i) printk(KERN_DEBUG "i2c-algo-bit.o: needed %d retries for %d\n", -- i,addr)); -+ DEB2(if (i) -+ printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n", -+ i+1, addr & 1 ? "read" : "write", addr>>1, -+ ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" ) -+ ); - return ret; - } - --static int sendbytes(struct i2c_adapter *i2c_adap,const char *buf, int count) -+static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) - { - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - char c; -- const char *temp = buf; -+ const char *temp = msg->buf; -+ int count = msg->len; -+ unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; - int retval; - int wrcount=0; - -@@ -358,7 +352,7 @@ - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s sendbytes: writing %2.2X\n", - i2c_adap->name, c&0xff)); - retval = i2c_outb(i2c_adap,c); -- if (retval>0) { -+ if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ - count--; - temp++; - wrcount++; -@@ -377,12 +371,18 @@ - return wrcount; - } - --static inline int readbytes(struct i2c_adapter *i2c_adap,char *buf,int count) -+static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) - { -- char *temp = buf; - int inval; - int rdcount=0; /* counts bytes read */ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; -+ char *temp = msg->buf; -+ int count = msg->len; -+ int recv_len = 0; -+ -+ /* Receive [Count] for I2C_SMBUS_BLOCK_DATA or I2C_SMBUS_BLOCK_PROC_CALL protocol */ -+ if (msg->flags & I2C_M_RECV_LEN) -+ recv_len = 1; - - while (count > 0) { - inval = i2c_inb(i2c_adap); -@@ -395,6 +395,20 @@ - break; - } - -+ if (recv_len) { -+ recv_len = 0; -+ /* [Count] should be between 1 and 31 (I2C_SMBUS_BLOCK_MAX - 1). */ -+ if (inval > 0 && inval < I2C_SMBUS_BLOCK_MAX) { -+ count = inval + 1; /* plus one for [Count] itself */ -+ msg->len = count; -+ if (msg->flags & I2C_M_RECV_PEC) -+ count++; /* plus one for PEC */ -+ } else { -+ printk(KERN_ERR "i2c-algo-bit.o: readbytes: bad block count (%d).\n", inval); -+ break; -+ } -+ } -+ - if ( count > 1 ) { /* send ack */ - sdalo(adap); - DEBPROTO(printk(" Am ")); -@@ -419,31 +433,34 @@ - * try_address) and transmits the address in the necessary format to handle - * reads, writes as well as 10bit-addresses. - * returns: -- * 0 everything went okay, the chip ack'ed -+ * 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set - * -x an error occurred (like: -EREMOTEIO if the device did not answer, or - * -ETIMEDOUT, for example if the lines are stuck...) - */ --static inline int bit_doAddress(struct i2c_adapter *i2c_adap, -- struct i2c_msg *msg, int retries) -+static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) - { - unsigned short flags = msg->flags; -+ unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - unsigned char addr; -- int ret; -+ int ret, retries; -+ -+ retries = nak_ok ? 0 : i2c_adap->retries; -+ - if ( (flags & I2C_M_TEN) ) { - /* a ten bit address */ - addr = 0xf0 | (( msg->addr >> 7) & 0x03); - DEB2(printk(KERN_DEBUG "addr0: %d\n",addr)); - /* try extended address code...*/ - ret = try_address(i2c_adap, addr, retries); -- if (ret!=1) { -+ if ((ret != 1) && !nak_ok) { - printk(KERN_ERR "died at extended address code.\n"); - return -EREMOTEIO; - } - /* the remaining 8 bit address */ - ret = i2c_outb(i2c_adap,msg->addr & 0x7f); -- if (ret != 1) { -+ if ((ret != 1) && !nak_ok) { - /* the chip did not ack / xmission error occurred */ - printk(KERN_ERR "died at 2nd address code.\n"); - return -EREMOTEIO; -@@ -453,7 +470,7 @@ - /* okay, now switch into reading mode */ - addr |= 0x01; - ret = try_address(i2c_adap, addr, retries); -- if (ret!=1) { -+ if ((ret!=1) && !nak_ok) { - printk(KERN_ERR "died at extended address code.\n"); - return -EREMOTEIO; - } -@@ -465,10 +482,10 @@ - if (flags & I2C_M_REV_DIR_ADDR ) - addr ^= 1; - ret = try_address(i2c_adap, addr, retries); -- if (ret!=1) { -+ if ((ret!=1) && !nak_ok) - return -EREMOTEIO; -- } - } -+ - return 0; - } - -@@ -479,16 +496,18 @@ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - int i,ret; -+ unsigned short nak_ok; - - i2c_start(adap); - for (i=0;i<num;i++) { - pmsg = &msgs[i]; -+ nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; - if (!(pmsg->flags & I2C_M_NOSTART)) { - if (i) { - i2c_repstart(adap); - } -- ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries); -- if (ret != 0) { -+ ret = bit_doAddress(i2c_adap, pmsg); -+ if ((ret != 0) && !nak_ok) { - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n", - msgs[i].addr,i)); - return (ret<0) ? ret : -EREMOTEIO; -@@ -496,14 +515,14 @@ - } - if (pmsg->flags & I2C_M_RD ) { - /* read bytes into buffer*/ -- ret = readbytes(i2c_adap,pmsg->buf,pmsg->len); -+ ret = readbytes(i2c_adap, pmsg); - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); - if (ret < pmsg->len ) { - return (ret<0)? ret : -EREMOTEIO; - } - } else { - /* write bytes from buffer */ -- ret = sendbytes(i2c_adap,pmsg->buf,pmsg->len); -+ ret = sendbytes(i2c_adap, pmsg); - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); - if (ret < pmsg->len ) { - return (ret<0) ? ret : -EREMOTEIO; -@@ -514,30 +533,25 @@ - return num; - } - --static int algo_control(struct i2c_adapter *adapter, -- unsigned int cmd, unsigned long arg) --{ -- return 0; --} -- --static u32 bit_func(struct i2c_adapter *adap) -+static u32 bit_func(struct i2c_adapter *i2c_adap) - { - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | -- I2C_FUNC_PROTOCOL_MANGLING; -+ I2C_FUNC_PROTOCOL_MANGLING | -+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL | -+ I2C_FUNC_SMBUS_READ_BLOCK_DATA | -+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC | -+ I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC; - } - - - /* -----exported algorithm data: ------------------------------------- */ - - static struct i2c_algorithm i2c_bit_algo = { -- "Bit-shift algorithm", -- I2C_ALGO_BIT, -- bit_xfer, -- NULL, -- NULL, /* slave_xmit */ -- NULL, /* slave_recv */ -- algo_control, /* ioctl */ -- bit_func, /* functionality */ -+ .owner = THIS_MODULE, -+ .name = "Bit-shift algorithm", -+ .id = I2C_ALGO_BIT, -+ .master_xfer = bit_xfer, -+ .functionality = bit_func, - }; - - /* -@@ -545,7 +559,6 @@ - */ - int i2c_bit_add_bus(struct i2c_adapter *adap) - { -- int i; - struct i2c_algo_bit_data *bit_adap = adap->algo_data; - - if (bit_test) { -@@ -565,78 +578,26 @@ - adap->timeout = 100; /* default values, should */ - adap->retries = 3; /* be replaced by defines */ - -- /* scan bus */ -- if (bit_scan) { -- int ack; -- printk(KERN_INFO " i2c-algo-bit.o: scanning bus %s.\n", -- adap->name); -- for (i = 0x00; i < 0xff; i+=2) { -- i2c_start(bit_adap); -- ack = i2c_outb(adap,i); -- i2c_stop(bit_adap); -- if (ack>0) { -- printk("(%02x)",i>>1); -- } else -- printk("."); -- } -- printk("\n"); -- } -- --#ifdef MODULE -- MOD_INC_USE_COUNT; --#endif - i2c_add_adapter(adap); -- - return 0; - } - - - int i2c_bit_del_bus(struct i2c_adapter *adap) - { -- int res; -- -- if ((res = i2c_del_adapter(adap)) < 0) -- return res; -- -- DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name)); -- --#ifdef MODULE -- MOD_DEC_USE_COUNT; --#endif -- return 0; --} -- --int __init i2c_algo_bit_init (void) --{ -- printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module\n"); -- return 0; -+ return i2c_del_adapter(adap); - } - -- -- - EXPORT_SYMBOL(i2c_bit_add_bus); - EXPORT_SYMBOL(i2c_bit_del_bus); - --#ifdef MODULE - MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); - MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); - MODULE_LICENSE("GPL"); - - 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"); -- --int init_module(void) --{ -- return i2c_algo_bit_init(); --} -- --void cleanup_module(void) --{ --} --#endif ---- linux-old/include/linux/i2c-algo-bit.h Sat Feb 5 06:47:38 2000 -+++ linux/include/linux/i2c-algo-bit.h Mon Dec 13 19:26:28 2004 -@@ -21,12 +21,10 @@ - /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even - Frodo Looijaard <frodol@dds.nl> */ - --/* $Id: i2c-algo-bit.h,v 1.7 1999/12/21 23:45:58 frodo Exp $ */ -+/* $Id: i2c-algo-bit.h,v 1.11 2003/07/25 07:56:42 khali Exp $ */ - --#ifndef I2C_ALGO_BIT_H --#define I2C_ALGO_BIT_H 1 -- --#include <linux/i2c.h> -+#ifndef _LINUX_I2C_ALGO_BIT_H -+#define _LINUX_I2C_ALGO_BIT_H - - /* --- Defines for bit-adapters --------------------------------------- */ - /* -@@ -42,9 +40,10 @@ - int (*getscl) (void *data); - - /* local settings */ -- int udelay; -- int mdelay; -- int timeout; -+ int udelay; /* half-clock-cycle time in microsecs */ -+ /* i.e. clock is (500 / udelay) KHz */ -+ int mdelay; /* in millisecs, unused */ -+ int timeout; /* in jiffies */ - }; - - #define I2C_BIT_ADAP_MAX 16 -@@ -52,4 +51,4 @@ - int i2c_bit_add_bus(struct i2c_adapter *); - int i2c_bit_del_bus(struct i2c_adapter *); - --#endif /* I2C_ALGO_BIT_H */ -+#endif /* _LINUX_I2C_ALGO_BIT_H */ ---- linux-old/drivers/i2c/i2c-algo-ibm_ocp.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-algo-ibm_ocp.c Mon Dec 13 19:26:29 2004 -@@ -0,0 +1,901 @@ -+/* -+ ------------------------------------------------------------------------- -+ i2c-algo-ibm_ocp.c i2c driver algorithms for IBM PPC 405 adapters -+ ------------------------------------------------------------------------- -+ -+ Ian DaSilva, MontaVista Software, Inc. -+ idasilva@mvista.com or source@mvista.com -+ -+ Copyright 2000 MontaVista Software Inc. -+ -+ Changes made to support the IIC peripheral on the IBM PPC 405 -+ -+ -+ --------------------------------------------------------------------------- -+ This file was highly leveraged from i2c-algo-pcf.c, which was created -+ by Simon G. Vogl and Hans Berglund: -+ -+ -+ Copyright (C) 1995-1997 Simon G. Vogl -+ 1998-2000 Hans Berglund -+ -+ With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and -+ Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey -+ <mbailey@littlefeet-inc.com> -+ -+ -+ 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. -+ --------------------------------------------------------------------------- -+ -+ History: 01/20/12 - Armin -+ akuster@mvista.com -+ ported up to 2.4.16+ -+ -+ Version 02/03/25 - Armin -+ converted to ocp format -+ removed commented out or #if 0 code -+ added Gérard Basler's fix to iic_combined_transaction() such that it -+ returns the number of successfully completed transfers . -+*/ -+ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/errno.h> -+#include <linux/sched.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-ibm_ocp.h> -+#include <asm/ocp.h> -+ -+ -+/* ----- global defines ----------------------------------------------- */ -+#define DEB(x) if (i2c_debug>=1) x -+#define DEB2(x) if (i2c_debug>=2) x -+#define DEB3(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 */ -+#define DEF_TIMEOUT 5 -+ -+ -+/* ----- global variables --------------------------------------------- */ -+ -+ -+/* module parameters: -+ */ -+static int i2c_debug=0; -+ -+/* --- setting states on the bus with the right timing: --------------- */ -+ -+#define iic_outb(adap, reg, val) adap->setiic(adap->data, (int) &(reg), val) -+#define iic_inb(adap, reg) adap->getiic(adap->data, (int) &(reg)) -+ -+#define IICO_I2C_SDAHIGH 0x0780 -+#define IICO_I2C_SDALOW 0x0781 -+#define IICO_I2C_SCLHIGH 0x0782 -+#define IICO_I2C_SCLLOW 0x0783 -+#define IICO_I2C_LINEREAD 0x0784 -+ -+#define IIC_SINGLE_XFER 0 -+#define IIC_COMBINED_XFER 1 -+ -+#define IIC_ERR_LOST_ARB -2 -+#define IIC_ERR_INCOMPLETE_XFR -3 -+#define IIC_ERR_NACK -1 -+ -+/* --- other auxiliary functions -------------------------------------- */ -+ -+ -+// -+// Description: Puts this process to sleep for a period equal to timeout -+// -+static inline void iic_sleep(unsigned long timeout) -+{ -+ schedule_timeout( timeout * HZ); -+} -+ -+ -+// -+// Description: This performs the IBM PPC 405 IIC initialization sequence -+// as described in the PPC405GP data book. -+// -+static int iic_init (struct i2c_algo_iic_data *adap) -+{ -+ struct iic_regs *iic; -+ struct iic_ibm *adap_priv_data = adap->data; -+ unsigned short retval; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ /* Clear master low master address */ -+ iic_outb(adap,iic->lmadr, 0); -+ -+ /* Clear high master address */ -+ iic_outb(adap,iic->hmadr, 0); -+ -+ /* Clear low slave address */ -+ iic_outb(adap,iic->lsadr, 0); -+ -+ /* Clear high slave address */ -+ iic_outb(adap,iic->hsadr, 0); -+ -+ /* Clear status */ -+ iic_outb(adap,iic->sts, 0x0a); -+ -+ /* Clear extended status */ -+ iic_outb(adap,iic->extsts, 0x8f); -+ -+ /* Set clock division */ -+ iic_outb(adap,iic->clkdiv, 0x04); -+ -+ retval = iic_inb(adap, iic->clkdiv); -+ DEB(printk("iic_init: CLKDIV register = %x\n", retval)); -+ -+ /* Enable interrupts on Requested Master Transfer Complete */ -+ iic_outb(adap,iic->intmsk, 0x01); -+ -+ /* Clear transfer count */ -+ iic_outb(adap,iic->xfrcnt, 0x0); -+ -+ /* Clear extended control and status */ -+ iic_outb(adap,iic->xtcntlss, 0xf0); -+ -+ /* Set mode control (flush master data buf, enable hold SCL, exit */ -+ /* unknown state. */ -+ iic_outb(adap,iic->mdcntl, 0x47); -+ -+ /* Clear control register */ -+ iic_outb(adap,iic->cntl, 0x0); -+ -+ DEB2(printk(KERN_DEBUG "iic_init: Initialized IIC on PPC 405\n")); -+ return 0; -+} -+ -+ -+// -+// Description: After we issue a transaction on the IIC bus, this function -+// is called. It puts this process to sleep until we get an interrupt from -+// from the controller telling us that the transaction we requested in complete. -+// -+static int wait_for_pin(struct i2c_algo_iic_data *adap, int *status) -+{ -+ -+ int timeout = DEF_TIMEOUT; -+ int retval; -+ struct iic_regs *iic; -+ struct iic_ibm *adap_priv_data = adap->data; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ -+ *status = iic_inb(adap, iic->sts); -+#ifndef STUB_I2C -+ -+ while (timeout-- && (*status & 0x01)) { -+ adap->waitforpin(adap->data); -+ *status = iic_inb(adap, iic->sts); -+ } -+#endif -+ if (timeout <= 0) { -+ /* Issue stop signal on the bus, and force an interrupt */ -+ retval = iic_inb(adap, iic->cntl); -+ iic_outb(adap, iic->cntl, retval | 0x80); -+ /* Clear status register */ -+ iic_outb(adap, iic->sts, 0x0a); -+ /* Exit unknown bus state */ -+ retval = iic_inb(adap, iic->mdcntl); -+ iic_outb(adap, iic->mdcntl, (retval | 0x02)); -+ -+ // Check the status of the controller. Does it still see a -+ // pending transfer, even though we've tried to stop any -+ // ongoing transaction? -+ retval = iic_inb(adap, iic->sts); -+ retval = retval & 0x01; -+ if(retval) { -+ // The iic controller is hosed. It is not responding to any -+ // of our commands. We have already tried to force it into -+ // a known state, but it has not worked. Our only choice now -+ // is a soft reset, which will clear all registers, and force -+ // us to re-initialize the controller. -+ /* Soft reset */ -+ iic_outb(adap, iic->xtcntlss, 0x01); -+ udelay(500); -+ iic_init(adap); -+ /* Is the pending transfer bit in the sts reg finally cleared? */ -+ retval = iic_inb(adap, iic->sts); -+ retval = retval & 0x01; -+ if(retval) { -+ printk(KERN_CRIT "The IIC Controller is hosed. A processor reset is required\n"); -+ } -+ // For some reason, even though the interrupt bit in this -+ // register was set during iic_init, it didn't take. We -+ // need to set it again. Don't ask me why....this is just what -+ // I saw when testing timeouts. -+ iic_outb(adap, iic->intmsk, 0x01); -+ } -+ return(-1); -+ } -+ else -+ return(0); -+} -+ -+ -+//------------------------------------ -+// Utility functions -+// -+ -+ -+// -+// Description: Look at the status register to see if there was an error -+// in the requested transaction. If there is, look at the extended status -+// register and determine the exact cause. -+// -+int analyze_status(struct i2c_algo_iic_data *adap, int *error_code) -+{ -+ int ret; -+ struct iic_regs *iic; -+ struct iic_ibm *adap_priv_data = adap->data; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ -+ ret = iic_inb(adap, iic->sts); -+ if(ret & 0x04) { -+ // Error occurred -+ ret = iic_inb(adap, iic->extsts); -+ if(ret & 0x04) { -+ // Lost arbitration -+ *error_code = IIC_ERR_LOST_ARB; -+ } -+ if(ret & 0x02) { -+ // Incomplete transfer -+ *error_code = IIC_ERR_INCOMPLETE_XFR; -+ } -+ if(ret & 0x01) { -+ // Master transfer aborted by a NACK during the transfer of the -+ // address byte -+ *error_code = IIC_ERR_NACK; -+ } -+ return -1; -+ } -+ return 0; -+} -+ -+ -+// -+// Description: This function is called by the upper layers to do the -+// grunt work for a master send transaction -+// -+static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf, -+ int count, int xfer_flag) -+{ -+ struct iic_regs *iic; -+ struct i2c_algo_iic_data *adap = i2c_adap->algo_data; -+ struct iic_ibm *adap_priv_data = adap->data; -+ int wrcount, status, timeout; -+ int loops, remainder, i, j; -+ int ret, error_code; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ -+ if( count == 0 ) return 0; -+ wrcount = 0; -+ loops = count / 4; -+ remainder = count % 4; -+ -+ if((loops > 1) && (remainder == 0)) { -+ for(i=0; i<(loops-1); i++) { -+ // -+ // Write four bytes to master data buffer -+ // -+ for(j=0; j<4; j++) { -+ iic_outb(adap, iic->mdbuf, -+ buf[wrcount++]); -+ } -+ // -+ // Issue command to IICO device to begin transmission -+ // -+ iic_outb(adap, iic->cntl, 0x35); -+ // -+ // Wait for transmission to complete. When it does, -+ //loop to the top of the for statement and write the -+ // next four bytes. -+ // -+ timeout = wait_for_pin(adap, &status); -+ if(timeout < 0) { -+ // -+ // Error handling -+ // -+ //printk(KERN_ERR "Error: write timeout\n"); -+ return wrcount; -+ } -+ ret = analyze_status(adap, &error_code); -+ if(ret < 0) { -+ if(error_code == IIC_ERR_INCOMPLETE_XFR) { -+ // Return the number of bytes transferred -+ ret = iic_inb(adap, iic->xfrcnt); -+ ret = ret & 0x07; -+ return (wrcount-4+ret); -+ } -+ else return error_code; -+ } -+ } -+ } -+ else if((loops >= 1) && (remainder > 0)){ -+ //printk(KERN_DEBUG "iic_sendbytes: (loops >= 1)\n"); -+ for(i=0; i<loops; i++) { -+ // -+ // Write four bytes to master data buffer -+ // -+ for(j=0; j<4; j++) { -+ iic_outb(adap, iic->mdbuf, -+ buf[wrcount++]); -+ } -+ // -+ // Issue command to IICO device to begin transmission -+ // -+ iic_outb(adap, iic->cntl, 0x35); -+ // -+ // Wait for transmission to complete. When it does, -+ //loop to the top of the for statement and write the -+ // next four bytes. -+ // -+ timeout = wait_for_pin(adap, &status); -+ if(timeout < 0) { -+ // -+ // Error handling -+ // -+ //printk(KERN_ERR "Error: write timeout\n"); -+ return wrcount; -+ } -+ ret = analyze_status(adap, &error_code); -+ if(ret < 0) { -+ if(error_code == IIC_ERR_INCOMPLETE_XFR) { -+ // Return the number of bytes transferred -+ ret = iic_inb(adap, iic->xfrcnt); -+ ret = ret & 0x07; -+ return (wrcount-4+ret); -+ } -+ else return error_code; -+ } -+ } -+ } -+ -+ //printk(KERN_DEBUG "iic_sendbytes: expedite write\n"); -+ if(remainder == 0) remainder = 4; -+ // remainder = remainder - 1; -+ // -+ // Write the remaining bytes (less than or equal to 4) -+ // -+ for(i=0; i<remainder; i++) { -+ iic_outb(adap, iic->mdbuf, buf[wrcount++]); -+ //printk(KERN_DEBUG "iic_sendbytes: data transferred = %x, wrcount = %d\n", buf[wrcount-1], (wrcount-1)); -+ } -+ //printk(KERN_DEBUG "iic_sendbytes: Issuing write\n"); -+ -+ if(xfer_flag == IIC_COMBINED_XFER) { -+ iic_outb(adap, iic->cntl, (0x09 | ((remainder-1) << 4))); -+ } -+ else { -+ iic_outb(adap, iic->cntl, (0x01 | ((remainder-1) << 4))); -+ } -+ DEB2(printk(KERN_DEBUG "iic_sendbytes: Waiting for interrupt\n")); -+ timeout = wait_for_pin(adap, &status); -+ if(timeout < 0) { -+ // -+ // Error handling -+ // -+ //printk(KERN_ERR "Error: write timeout\n"); -+ return wrcount; -+ } -+ ret = analyze_status(adap, &error_code); -+ if(ret < 0) { -+ if(error_code == IIC_ERR_INCOMPLETE_XFR) { -+ // Return the number of bytes transferred -+ ret = iic_inb(adap, iic->xfrcnt); -+ ret = ret & 0x07; -+ return (wrcount-4+ret); -+ } -+ else return error_code; -+ } -+ DEB2(printk(KERN_DEBUG "iic_sendbytes: Got interrupt\n")); -+ return wrcount; -+} -+ -+ -+// -+// Description: Called by the upper layers to do the grunt work for -+// a master read transaction. -+// -+static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count, int xfer_type) -+{ -+ struct iic_regs *iic; -+ int rdcount=0, i, status, timeout; -+ struct i2c_algo_iic_data *adap = i2c_adap->algo_data; -+ struct iic_ibm *adap_priv_data = adap->data; -+ int loops, remainder, j; -+ int ret, error_code; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ if(count == 0) return 0; -+ loops = count / 4; -+ remainder = count % 4; -+ -+ //printk(KERN_DEBUG "iic_readbytes: loops = %d, remainder = %d\n", loops, remainder); -+ -+ if((loops > 1) && (remainder == 0)) { -+ //printk(KERN_DEBUG "iic_readbytes: (loops > 1) && (remainder == 0)\n"); -+ for(i=0; i<(loops-1); i++) { -+ // -+ // Issue command to begin master read (4 bytes maximum) -+ // -+ //printk(KERN_DEBUG "--->Issued read command\n"); -+ iic_outb(adap, iic->cntl, 0x37); -+ // -+ // Wait for transmission to complete. When it does, -+ // loop to the top of the for statement and write the -+ // next four bytes. -+ // -+ //printk(KERN_DEBUG "--->Waiting for interrupt\n"); -+ timeout = wait_for_pin(adap, &status); -+ if(timeout < 0) { -+ // Error Handler -+ //printk(KERN_ERR "Error: read timed out\n"); -+ return rdcount; -+ } -+ //printk(KERN_DEBUG "--->Got interrupt\n"); -+ -+ ret = analyze_status(adap, &error_code); -+ if(ret < 0) { -+ if(error_code == IIC_ERR_INCOMPLETE_XFR) -+ return rdcount; -+ else -+ return error_code; -+ } -+ -+ for(j=0; j<4; j++) { -+ // Wait for data to shuffle to top of data buffer -+ // This value needs to optimized. -+ udelay(1); -+ buf[rdcount] = iic_inb(adap, iic->mdbuf); -+ rdcount++; -+ //printk(KERN_DEBUG "--->Read one byte\n"); -+ } -+ } -+ } -+ -+ else if((loops >= 1) && (remainder > 0)){ -+ //printk(KERN_DEBUG "iic_readbytes: (loops >=1) && (remainder > 0)\n"); -+ for(i=0; i<loops; i++) { -+ // -+ // Issue command to begin master read (4 bytes maximum) -+ // -+ //printk(KERN_DEBUG "--->Issued read command\n"); -+ iic_outb(adap, iic->cntl, 0x37); -+ // -+ // Wait for transmission to complete. When it does, -+ // loop to the top of the for statement and write the -+ // next four bytes. -+ // -+ //printk(KERN_DEBUG "--->Waiting for interrupt\n"); -+ timeout = wait_for_pin(adap, &status); -+ if(timeout < 0) { -+ // Error Handler -+ //printk(KERN_ERR "Error: read timed out\n"); -+ return rdcount; -+ } -+ //printk(KERN_DEBUG "--->Got interrupt\n"); -+ -+ ret = analyze_status(adap, &error_code); -+ if(ret < 0) { -+ if(error_code == IIC_ERR_INCOMPLETE_XFR) -+ return rdcount; -+ else -+ return error_code; -+ } -+ -+ for(j=0; j<4; j++) { -+ // Wait for data to shuffle to top of data buffer -+ // This value needs to optimized. -+ udelay(1); -+ buf[rdcount] = iic_inb(adap, iic->mdbuf); -+ rdcount++; -+ //printk(KERN_DEBUG "--->Read one byte\n"); -+ } -+ } -+ } -+ -+ //printk(KERN_DEBUG "iic_readbytes: expedite read\n"); -+ if(remainder == 0) remainder = 4; -+ DEB2(printk(KERN_DEBUG "iic_readbytes: writing %x to IICO_CNTL\n", (0x03 | ((remainder-1) << 4)))); -+ -+ if(xfer_type == IIC_COMBINED_XFER) { -+ iic_outb(adap, iic->cntl, (0x0b | ((remainder-1) << 4))); -+ } -+ else { -+ iic_outb(adap, iic->cntl, (0x03 | ((remainder-1) << 4))); -+ } -+ DEB2(printk(KERN_DEBUG "iic_readbytes: Wait for pin\n")); -+ timeout = wait_for_pin(adap, &status); -+ DEB2(printk(KERN_DEBUG "iic_readbytes: Got the interrupt\n")); -+ if(timeout < 0) { -+ // Error Handler -+ //printk(KERN_ERR "Error: read timed out\n"); -+ return rdcount; -+ } -+ -+ ret = analyze_status(adap, &error_code); -+ if(ret < 0) { -+ if(error_code == IIC_ERR_INCOMPLETE_XFR) -+ return rdcount; -+ else -+ return error_code; -+ } -+ -+ //printk(KERN_DEBUG "iic_readbyte: Begin reading data buffer\n"); -+ for(i=0; i<remainder; i++) { -+ buf[rdcount] = iic_inb(adap, iic->mdbuf); -+ // printk(KERN_DEBUG "iic_readbytes: Character read = %x\n", buf[rdcount]); -+ rdcount++; -+ } -+ -+ return rdcount; -+} -+ -+ -+// -+// Description: This function implements combined transactions. Combined -+// transactions consist of combinations of reading and writing blocks of data. -+// Each transfer (i.e. a read or a write) is separated by a repeated start -+// condition. -+// -+static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -+{ -+ int i; -+ struct i2c_msg *pmsg; -+ int ret; -+ -+ DEB2(printk(KERN_DEBUG "Beginning combined transaction\n")); -+ for(i=0; i < num; i++) { -+ pmsg = &msgs[i]; -+ if(pmsg->flags & I2C_M_RD) { -+ -+ // Last read or write segment needs to be terminated with a stop -+ if(i < num-1) { -+ DEB2(printk(KERN_DEBUG "This one is a read\n")); -+ } -+ else { -+ DEB2(printk(KERN_DEBUG "Doing the last read\n")); -+ } -+ ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, (i < num-1) ? IIC_COMBINED_XFER : IIC_SINGLE_XFER); -+ -+ if (ret != pmsg->len) { -+ DEB2(printk("i2c-algo-ppc405.o: fail: " -+ "only read %d bytes.\n",ret)); -+ return i; -+ } -+ else { -+ DEB2(printk("i2c-algo-ppc405.o: read %d bytes.\n",ret)); -+ } -+ } -+ else if(!(pmsg->flags & I2C_M_RD)) { -+ -+ // Last read or write segment needs to be terminated with a stop -+ if(i < num-1) { -+ DEB2(printk(KERN_DEBUG "This one is a write\n")); -+ } -+ else { -+ DEB2(printk(KERN_DEBUG "Doing the last write\n")); -+ } -+ ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, (i < num-1) ? IIC_COMBINED_XFER : IIC_SINGLE_XFER); -+ -+ if (ret != pmsg->len) { -+ DEB2(printk("i2c-algo-ppc405.o: fail: " -+ "only wrote %d bytes.\n",ret)); -+ return i; -+ } -+ else { -+ DEB2(printk("i2c-algo-ppc405.o: wrote %d bytes.\n",ret)); -+ } -+ } -+ } -+ -+ return num; -+} -+ -+ -+// -+// Description: Whenever we initiate a transaction, the first byte clocked -+// onto the bus after the start condition is the address (7 bit) of the -+// device we want to talk to. This function manipulates the address specified -+// so that it makes sense to the hardware when written to the IIC peripheral. -+// -+// Note: 10 bit addresses are not supported in this driver, although they are -+// supported by the hardware. This functionality needs to be implemented. -+// -+static inline int iic_doAddress(struct i2c_algo_iic_data *adap, -+ struct i2c_msg *msg, int retries) -+{ -+ struct iic_regs *iic; -+ unsigned short flags = msg->flags; -+ unsigned char addr; -+ struct iic_ibm *adap_priv_data = adap->data; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+// -+// The following segment for 10 bit addresses needs to be ported -+// -+/* Ten bit addresses not supported right now -+ if ( (flags & I2C_M_TEN) ) { -+ // a ten bit address -+ addr = 0xf0 | (( msg->addr >> 7) & 0x03); -+ DEB2(printk(KERN_DEBUG "addr0: %d\n",addr)); -+ // try extended address code... -+ ret = try_address(adap, addr, retries); -+ if (ret!=1) { -+ printk(KERN_ERR "iic_doAddress: died at extended address code.\n"); -+ return -EREMOTEIO; -+ } -+ // the remaining 8 bit address -+ iic_outb(adap,msg->addr & 0x7f); -+ // Status check comes here -+ if (ret != 1) { -+ printk(KERN_ERR "iic_doAddress: 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(KERN_ERR "iic_doAddress: died at extended address code.\n"); -+ return -EREMOTEIO; -+ } -+ } -+ } else ----------> // normal 7 bit address -+ -+Ten bit addresses not supported yet */ -+ -+ addr = ( msg->addr << 1 ); -+ if (flags & I2C_M_RD ) -+ addr |= 1; -+ if (flags & I2C_M_REV_DIR_ADDR ) -+ addr ^= 1; -+ // -+ // Write to the low slave address -+ // -+ iic_outb(adap, iic->lmadr, addr); -+ // -+ // Write zero to the high slave register since we are -+ // only using 7 bit addresses -+ // -+ iic_outb(adap, iic->hmadr, 0); -+ -+ return 0; -+} -+ -+ -+// -+// Description: Prepares the controller for a transaction (clearing status -+// registers, data buffers, etc), and then calls either iic_readbytes or -+// iic_sendbytes to do the actual transaction. -+// -+static int iic_xfer(struct i2c_adapter *i2c_adap, -+ struct i2c_msg msgs[], -+ int num) -+{ -+ struct iic_regs *iic; -+ struct i2c_algo_iic_data *adap = i2c_adap->algo_data; -+ struct iic_ibm *adap_priv_data = adap->data; -+ struct i2c_msg *pmsg; -+ int i = 0; -+ int ret; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ pmsg = &msgs[i]; -+ -+ // -+ // Clear status register -+ // -+ DEB2(printk(KERN_DEBUG "iic_xfer: iic_xfer: Clearing status register\n")); -+ iic_outb(adap, iic->sts, 0x0a); -+ -+ // -+ // Wait for any pending transfers to complete -+ // -+ DEB2(printk(KERN_DEBUG "iic_xfer: Waiting for any pending transfers to complete\n")); -+ while((ret = iic_inb(adap, iic->sts)) == 0x01) { -+ ; -+ } -+ -+ // -+ // Flush master data buf -+ // -+ DEB2(printk(KERN_DEBUG "iic_xfer: Clearing master data buffer\n")); -+ ret = iic_inb(adap, iic->mdcntl); -+ iic_outb(adap, iic->mdcntl, ret | 0x40); -+ -+ // -+ // Load slave address -+ // -+ DEB2(printk(KERN_DEBUG "iic_xfer: Loading slave address\n")); -+ ret = iic_doAddress(adap, pmsg, i2c_adap->retries); -+ -+ // -+ // Check to see if the bus is busy -+ // -+ ret = iic_inb(adap, iic->extsts); -+ // Mask off the irrelevent bits -+ ret = ret & 0x70; -+ // When the bus is free, the BCS bits in the EXTSTS register are 0b100 -+ if(ret != 0x40) return IIC_ERR_LOST_ARB; -+ -+ // -+ // Combined transaction (read and write) -+ // -+ if(num > 1) { -+ DEB2(printk(KERN_DEBUG "iic_xfer: Call combined transaction\n")); -+ ret = iic_combined_transaction(i2c_adap, msgs, num); -+ } -+ // -+ // Read only -+ // -+ else if((num == 1) && (pmsg->flags & I2C_M_RD)) { -+ // -+ // Tell device to begin reading data from the master data -+ // -+ DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's read\n")); -+ ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); -+ } -+ // -+ // Write only -+ // -+ else if((num == 1 ) && (!(pmsg->flags & I2C_M_RD))) { -+ // -+ // Write data to master data buffers and tell our device -+ // to begin transmitting -+ // -+ DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's write\n")); -+ ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); -+ } -+ -+ return ret; -+} -+ -+ -+// -+// Description: Implements device specific ioctls. Higher level ioctls can -+// be found in i2c-core.c and are typical of any i2c controller (specifying -+// slave address, timeouts, etc). These ioctls take advantage of any hardware -+// features built into the controller for which this algorithm-adapter set -+// was written. These ioctls allow you to take control of the data and clock -+// lines on the IBM PPC 405 IIC controller and set the either high or low, -+// similar to a GPIO pin. -+// -+static int algo_control(struct i2c_adapter *adapter, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct iic_regs *iic; -+ struct i2c_algo_iic_data *adap = adapter->algo_data; -+ struct iic_ibm *adap_priv_data = adap->data; -+ int ret=0; -+ int lines; -+ iic = (struct iic_regs *) adap_priv_data->iic_base; -+ -+ lines = iic_inb(adap, iic->directcntl); -+ -+ if (cmd == IICO_I2C_SDAHIGH) { -+ lines = lines & 0x01; -+ if( lines ) lines = 0x04; -+ else lines = 0; -+ iic_outb(adap, iic->directcntl,(0x08|lines)); -+ } -+ else if (cmd == IICO_I2C_SDALOW) { -+ lines = lines & 0x01; -+ if( lines ) lines = 0x04; -+ else lines = 0; -+ iic_outb(adap, iic->directcntl,(0x00|lines)); -+ } -+ else if (cmd == IICO_I2C_SCLHIGH) { -+ lines = lines & 0x02; -+ if( lines ) lines = 0x08; -+ else lines = 0; -+ iic_outb(adap, iic->directcntl,(0x04|lines)); -+ } -+ else if (cmd == IICO_I2C_SCLLOW) { -+ lines = lines & 0x02; -+ if( lines ) lines = 0x08; -+ else lines = 0; -+ iic_outb(adap, iic->directcntl,(0x00|lines)); -+ } -+ else if (cmd == IICO_I2C_LINEREAD) { -+ ret = lines; -+ } -+ return ret; -+} -+ -+ -+static u32 iic_func(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | -+ I2C_FUNC_PROTOCOL_MANGLING; -+} -+ -+ -+/* -----exported algorithm data: ------------------------------------- */ -+ -+static struct i2c_algorithm iic_algo = { -+ .owner = THIS_MODULE, -+ .name = "IBM on-chip IIC algorithm", -+ .id = I2C_ALGO_OCP, -+ .master_xfer = iic_xfer, -+ .algo_control = algo_control, -+ .functionality = iic_func, -+}; -+ -+/* -+ * registering functions to load algorithms at runtime -+ */ -+ -+ -+// -+// Description: Register bus structure -+// -+int i2c_ocp_add_bus(struct i2c_adapter *adap) -+{ -+ struct i2c_algo_iic_data *iic_adap = adap->algo_data; -+ -+ DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: hw routines for %s registered.\n", -+ adap->name)); -+ -+ /* register new adapter to i2c module... */ -+ -+ adap->id |= iic_algo.id; -+ adap->algo = &iic_algo; -+ -+ adap->timeout = 100; /* default values, should */ -+ adap->retries = 3; /* be replaced by defines */ -+ -+ iic_init(iic_adap); -+ i2c_add_adapter(adap); -+ return 0; -+} -+ -+ -+// -+// Done -+// -+int i2c_ocp_del_bus(struct i2c_adapter *adap) -+{ -+ return i2c_del_adapter(adap); -+} -+ -+ -+EXPORT_SYMBOL(i2c_ocp_add_bus); -+EXPORT_SYMBOL(i2c_ocp_del_bus); -+ -+// -+// The MODULE_* macros resolve to nothing if MODULES is not defined -+// when this file is compiled. -+// -+MODULE_AUTHOR("MontaVista Software <www.mvista.com>"); -+MODULE_DESCRIPTION("PPC 405 iic algorithm"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(i2c_debug,"i"); -+ -+MODULE_PARM_DESC(i2c_debug, -+ "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); -+ ---- linux-old/include/linux/i2c-algo-ibm_ocp.h Thu Jan 1 00:00:00 1970 -+++ linux/include/linux/i2c-algo-ibm_ocp.h Mon Dec 13 19:26:29 2004 -@@ -0,0 +1,52 @@ -+/* ------------------------------------------------------------------------- */ -+/* i2c-algo-ibm_ocp.h i2c driver algorithms for IBM PPC 405 IIC adapters */ -+/* ------------------------------------------------------------------------- */ -+/* Copyright (C) 1995-97 Simon G. Vogl -+ 1998-99 Hans Berglund -+ -+ 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 <kmalkki@cc.hut.fi> and even -+ Frodo Looijaard <frodol@dds.nl> */ -+ -+/* Modifications by MontaVista Software, August 2000 -+ Changes made to support the IIC peripheral on the IBM PPC 405 */ -+ -+#ifndef _LINUX_I2C_ALGO_IBM_OCP_H -+#define _LINUX_I2C_ALGO_IBM_OCP_H -+ -+struct i2c_algo_iic_data { -+ struct iic_regs *data; /* private data for lolevel routines */ -+ void (*setiic) (void *data, int ctl, int val); -+ int (*getiic) (void *data, int ctl); -+ int (*getown) (void *data); -+ int (*getclock) (void *data); -+ void (*waitforpin) (void *data); -+ -+ /* local settings */ -+ int udelay; -+ int mdelay; -+ int timeout; -+}; -+ -+ -+#define I2C_IIC_ADAP_MAX 16 -+ -+ -+int i2c_ocp_add_bus(struct i2c_adapter *); -+int i2c_ocp_del_bus(struct i2c_adapter *); -+ -+#endif /* _LINUX_I2C_ALGO_IBM_OCP_H */ ---- linux-old/drivers/i2c/i2c-algo-pcf.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-algo-pcf.c Mon Dec 13 19:26:29 2004 -@@ -32,14 +32,11 @@ - #include <linux/delay.h> - #include <linux/slab.h> - #include <linux/init.h> --#include <asm/uaccess.h> --#include <linux/ioport.h> - #include <linux/errno.h> - #include <linux/sched.h> -- - #include <linux/i2c.h> - #include <linux/i2c-algo-pcf.h> --#include "i2c-pcf8584.h" -+ - - /* ----- global defines ----------------------------------------------- */ - #define DEB(x) if (i2c_debug>=1) x -@@ -52,7 +49,6 @@ - /* module parameters: - */ - static int i2c_debug=0; --static int pcf_scan=0; /* have a look at what's hanging 'round */ - - /* --- setting states on the bus with the right timing: --------------- */ - -@@ -149,8 +145,7 @@ - set_pcf(adap, 1, I2C_PCF_PIN); - /* check to see S1 now used as R/W ctrl - - PCF8584 does that when ESO is zero */ -- /* PCF also resets PIN bit */ -- if ((temp = get_pcf(adap, 1)) != (0)) { -+ if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp)); - return -ENXIO; /* definetly not PCF8584 */ - } -@@ -166,7 +161,7 @@ - /* S1=0xA0, next byte in S2 */ - set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1); - /* check to see S2 now selected */ -- if ((temp = get_pcf(adap, 1)) != I2C_PCF_ES1) { -+ if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S2 (0x%02x).\n", temp)); - return -ENXIO; - } -@@ -427,12 +422,6 @@ - return (i); - } - --static int algo_control(struct i2c_adapter *adapter, -- unsigned int cmd, unsigned long arg) --{ -- return 0; --} -- - static u32 pcf_func(struct i2c_adapter *adap) - { - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | -@@ -442,14 +431,11 @@ - /* -----exported algorithm data: ------------------------------------- */ - - static struct i2c_algorithm pcf_algo = { -- "PCF8584 algorithm", -- I2C_ALGO_PCF, -- pcf_xfer, -- NULL, -- NULL, /* slave_xmit */ -- NULL, /* slave_recv */ -- algo_control, /* ioctl */ -- pcf_func, /* functionality */ -+ .owner = THIS_MODULE, -+ .name = "PCF8584 algorithm", -+ .id = I2C_ALGO_PCF, -+ .master_xfer = pcf_xfer, -+ .functionality = pcf_func, - }; - - /* -@@ -457,7 +443,7 @@ - */ - int i2c_pcf_add_bus(struct i2c_adapter *adap) - { -- int i, status; -+ int i; - struct i2c_algo_pcf_data *pcf_adap = adap->algo_data; - - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: hw routines for %s registered.\n", -@@ -475,81 +461,23 @@ - return i; - } - --#ifdef MODULE -- MOD_INC_USE_COUNT; --#endif -- - i2c_add_adapter(adap); -- -- /* scan bus */ -- if (pcf_scan) { -- printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n", -- adap->name); -- for (i = 0x00; i < 0xff; i+=2) { -- if (wait_for_bb(pcf_adap)) { -- printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s - TIMEOUTed.\n", -- adap->name); -- break; -- } -- i2c_outb(pcf_adap, i); -- i2c_start(pcf_adap); -- if ((wait_for_pin(pcf_adap, &status) >= 0) && -- ((status & I2C_PCF_LRB) == 0)) { -- printk("(%02x)",i>>1); -- } else { -- printk("."); -- } -- i2c_stop(pcf_adap); -- udelay(pcf_adap->udelay); -- } -- printk("\n"); -- } - return 0; - } - - - int i2c_pcf_del_bus(struct i2c_adapter *adap) - { -- int res; -- if ((res = i2c_del_adapter(adap)) < 0) -- return res; -- DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name)); -- --#ifdef MODULE -- MOD_DEC_USE_COUNT; --#endif -- return 0; --} -- --int __init i2c_algo_pcf_init (void) --{ -- printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n"); -- return 0; -+ return i2c_del_adapter(adap); - } - -- - EXPORT_SYMBOL(i2c_pcf_add_bus); - EXPORT_SYMBOL(i2c_pcf_del_bus); - --#ifdef MODULE - MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); - MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); - MODULE_LICENSE("GPL"); - --MODULE_PARM(pcf_scan, "i"); - MODULE_PARM(i2c_debug,"i"); -- --MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus"); - MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); -- -- --int init_module(void) --{ -- return i2c_algo_pcf_init(); --} -- --void cleanup_module(void) --{ --} --#endif ---- linux-old/include/linux/i2c-algo-pcf.h Thu Mar 23 02:26:01 2000 -+++ linux/include/linux/i2c-algo-pcf.h Mon Dec 13 19:26:30 2004 -@@ -22,13 +22,12 @@ - /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even - Frodo Looijaard <frodol@dds.nl> */ - --/* $Id: i2c-algo-pcf.h,v 1.7 2000/02/27 23:02:45 frodo Exp $ */ -+/* $Id: i2c-algo-pcf.h,v 1.9 2003/07/25 07:56:42 khali Exp $ */ - --#ifndef I2C_ALGO_PCF_H --#define I2C_ALGO_PCF_H 1 -+#ifndef _LINUX_I2C_ALGO_PCF_H -+#define _LINUX_I2C_ALGO_PCF_H - --/* --- Defines for pcf-adapters --------------------------------------- */ --#include <linux/i2c.h> -+#include <linux/i2c-pcf8584.h> - - struct i2c_algo_pcf_data { - void *data; /* private data for lolevel routines */ -@@ -49,4 +48,4 @@ - int i2c_pcf_add_bus(struct i2c_adapter *); - int i2c_pcf_del_bus(struct i2c_adapter *); - --#endif /* I2C_ALGO_PCF_H */ -+#endif /* _LINUX_I2C_ALGO_PCF_H */ ---- linux-old/drivers/i2c/i2c-core.c Wed Jul 7 00:38:02 2004 -+++ linux/drivers/i2c/i2c-core.c Mon Dec 13 19:26:31 2004 -@@ -18,56 +18,33 @@ - /* ------------------------------------------------------------------------- */ - - /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. -- All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */ -+ All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> -+ SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */ - --/* $Id: i2c-core.c,v 1.64 2001/08/13 01:35:56 mds Exp $ */ -+/* i2c-core.c,v 1.91.2.2 2003/01/21 10:00:19 kmalkki Exp */ - - #include <linux/module.h> - #include <linux/kernel.h> - #include <linux/errno.h> - #include <linux/slab.h> - #include <linux/proc_fs.h> --#include <linux/config.h> -- --#include <linux/i2c.h> -- --/* ----- compatibility stuff ----------------------------------------------- */ -- - #include <linux/init.h> -- -+#include <linux/i2c.h> - #include <asm/uaccess.h> - - /* ----- global defines ---------------------------------------------------- */ - --/* exclusive access to the bus */ --#define I2C_LOCK(adap) down(&adap->lock) --#define I2C_UNLOCK(adap) up(&adap->lock) -- --#define ADAP_LOCK() down(&adap_lock) --#define ADAP_UNLOCK() up(&adap_lock) -- --#define DRV_LOCK() down(&driver_lock) --#define DRV_UNLOCK() up(&driver_lock) -- - #define DEB(x) if (i2c_debug>=1) x; - #define DEB2(x) if (i2c_debug>=2) x; - - /* ----- global variables -------------------------------------------------- */ - --/**** lock for writing to global variables: the adapter & driver list */ --struct semaphore adap_lock; --struct semaphore driver_lock; -- --/**** adapter list */ -+DECLARE_MUTEX(core_lists); - static struct i2c_adapter *adapters[I2C_ADAP_MAX]; --static int adap_count; -- --/**** drivers list */ - static struct i2c_driver *drivers[I2C_DRIVER_MAX]; --static int driver_count; - - /**** debug level */ --static int i2c_debug=1; -+static int i2c_debug; - - /* --------------------------------------------------- - * /proc entry declarations -@@ -75,10 +52,6 @@ - */ - - #ifdef CONFIG_PROC_FS -- --static int i2cproc_init(void); --static int i2cproc_cleanup(void); -- - static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos); - static int read_bus_i2c(char *buf, char **start, off_t offset, int len, -@@ -87,15 +60,11 @@ - /* To implement the dynamic /proc/bus/i2c-? files, we need our own - implementation of the read hook */ - static struct file_operations i2cproc_operations = { -- read: i2cproc_bus_read, -+ .read = i2cproc_bus_read, - }; - --static int i2cproc_initialized = 0; -- --#else /* undef CONFIG_PROC_FS */ -- --#define i2cproc_init() 0 --#define i2cproc_cleanup() 0 -+static int i2cproc_register(struct i2c_adapter *adap, int bus); -+static void i2cproc_remove(int bus); - - #endif /* CONFIG_PROC_FS */ - -@@ -112,9 +81,9 @@ - */ - int i2c_add_adapter(struct i2c_adapter *adap) - { -- int i,j,res; -+ int i,j,res = 0; - -- ADAP_LOCK(); -+ down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (NULL == adapters[i]) - break; -@@ -125,68 +94,39 @@ - res = -ENOMEM; - goto ERROR0; - } -+ -+#ifdef CONFIG_PROC_FS -+ res = i2cproc_register(adap, i); -+ if (res<0) -+ goto ERROR0; -+#endif /* def CONFIG_PROC_FS */ - - adapters[i] = adap; -- adap_count++; -- ADAP_UNLOCK(); - - /* init data types */ -- init_MUTEX(&adap->lock); -- --#ifdef CONFIG_PROC_FS -- -- if (i2cproc_initialized) { -- char name[8]; -- struct proc_dir_entry *proc_entry; -- -- sprintf(name,"i2c-%d", i); -- -- proc_entry = create_proc_entry(name,0,proc_bus); -- if (! proc_entry) { -- printk("i2c-core.o: Could not create /proc/bus/%s\n", -- name); -- res = -ENOENT; -- goto ERROR1; -- } -- -- proc_entry->proc_fops = &i2cproc_operations; -- proc_entry->owner = THIS_MODULE; -- adap->inode = proc_entry->low_ino; -- } -- --#endif /* def CONFIG_PROC_FS */ -+ init_MUTEX(&adap->bus); -+ init_MUTEX(&adap->list); - - /* inform drivers of new adapters */ -- DRV_LOCK(); - for (j=0;j<I2C_DRIVER_MAX;j++) - if (drivers[j]!=NULL && - (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY))) - /* We ignore the return code; if it fails, too bad */ - drivers[j]->attach_adapter(adap); -- DRV_UNLOCK(); - - DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n", - adap->name,i)); -- -- return 0; -- -- --ERROR1: -- ADAP_LOCK(); -- adapters[i] = NULL; -- adap_count--; - ERROR0: -- ADAP_UNLOCK(); -+ up(&core_lists); - return res; - } - - - int i2c_del_adapter(struct i2c_adapter *adap) - { -- int i,j,res; -- -- ADAP_LOCK(); -+ int i,j,res = 0; - -+ down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - break; -@@ -202,20 +142,17 @@ - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ -- DRV_LOCK(); - for (j = 0; j < I2C_DRIVER_MAX; j++) - if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) - if ((res = drivers[j]->attach_adapter(adap))) { - printk(KERN_WARNING "i2c-core.o: can't detach adapter %s " - "while detaching driver %s: driver not " - "detached!",adap->name,drivers[j]->name); -- goto ERROR1; -+ goto ERROR0; - } -- DRV_UNLOCK(); -- - - /* detach any active clients. This must be done first, because -- * it can fail; in which case we give upp. */ -+ * it can fail; in which case we give up. */ - for (j=0;j<I2C_CLIENT_MAX;j++) { - struct i2c_client *client = adap->clients[j]; - if (client!=NULL) -@@ -231,26 +168,15 @@ - goto ERROR0; - } - } -+ - #ifdef CONFIG_PROC_FS -- if (i2cproc_initialized) { -- char name[8]; -- sprintf(name,"i2c-%d", i); -- remove_proc_entry(name,proc_bus); -- } -+ i2cproc_remove(i); - #endif /* def CONFIG_PROC_FS */ - - adapters[i] = NULL; -- adap_count--; -- -- ADAP_UNLOCK(); - DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name)); -- return 0; -- - ERROR0: -- ADAP_UNLOCK(); -- return res; --ERROR1: -- DRV_UNLOCK(); -+ up(&core_lists); - return res; - } - -@@ -264,7 +190,8 @@ - int i2c_add_driver(struct i2c_driver *driver) - { - int i; -- DRV_LOCK(); -+ -+ down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (NULL == drivers[i]) - break; -@@ -273,19 +200,12 @@ - " i2c-core.o: register_driver(%s) " - "- enlarge I2C_DRIVER_MAX.\n", - driver->name); -- DRV_UNLOCK(); -+ up(&core_lists); - return -ENOMEM; - } -- - drivers[i] = driver; -- driver_count++; -- -- DRV_UNLOCK(); /* driver was successfully added */ -- - DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); - -- ADAP_LOCK(); -- - /* now look for instances of driver on our adapters - */ - if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { -@@ -294,15 +214,15 @@ - /* Ignore errors */ - driver->attach_adapter(adapters[i]); - } -- ADAP_UNLOCK(); -+ up(&core_lists); - return 0; - } - - int i2c_del_driver(struct i2c_driver *driver) - { -- int i,j,k,res; -+ int i,j,k,res = 0; - -- DRV_LOCK(); -+ down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (driver == drivers[i]) - break; -@@ -310,7 +230,7 @@ - printk(KERN_WARNING " i2c-core.o: unregister_driver: " - "[%s] not found\n", - driver->name); -- DRV_UNLOCK(); -+ up(&core_lists); - return -ENODEV; - } - /* Have a look at each adapter, if clients of this driver are still -@@ -322,7 +242,6 @@ - * invalid operation might (will!) result, when using stale client - * pointers. - */ -- ADAP_LOCK(); /* should be moved inside the if statement... */ - for (k=0;k<I2C_ADAP_MAX;k++) { - struct i2c_adapter *adap = adapters[k]; - if (adap == NULL) /* skip empty entries. */ -@@ -341,8 +260,7 @@ - "not be detached properly; driver " - "not unloaded!",driver->name, - adap->name); -- ADAP_UNLOCK(); -- return res; -+ goto ERROR0; - } - } else { - for (j=0;j<I2C_CLIENT_MAX;j++) { -@@ -359,37 +277,47 @@ - "unregistering driver " - "`%s', the client at " - "address %02x of " -- "adapter `%s' could not" -- "be detached; driver" -+ "adapter `%s' could not " -+ "be detached; driver " - "not unloaded!", - driver->name, - client->addr, - adap->name); -- ADAP_UNLOCK(); -- return res; -+ goto ERROR0; - } - } - } - } - } -- ADAP_UNLOCK(); - drivers[i] = NULL; -- driver_count--; -- DRV_UNLOCK(); -- - DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name)); -- return 0; -+ -+ERROR0: -+ up(&core_lists); -+ return res; - } - --int i2c_check_addr (struct i2c_adapter *adapter, int addr) -+static int __i2c_check_addr (struct i2c_adapter *adapter, int addr) - { - int i; - for (i = 0; i < I2C_CLIENT_MAX ; i++) - if (adapter->clients[i] && (adapter->clients[i]->addr == addr)) - return -EBUSY; -+ - return 0; - } - -+int i2c_check_addr (struct i2c_adapter *adapter, int addr) -+{ -+ int rval; -+ -+ down(&adapter->list); -+ rval = __i2c_check_addr(adapter, addr); -+ up(&adapter->list); -+ -+ return rval; -+} -+ - int i2c_attach_client(struct i2c_client *client) - { - struct i2c_adapter *adapter = client->adapter; -@@ -398,6 +326,7 @@ - if (i2c_check_addr(client->adapter,client->addr)) - return -EBUSY; - -+ down(&adapter->list); - for (i = 0; i < I2C_CLIENT_MAX; i++) - if (NULL == adapter->clients[i]) - break; -@@ -405,11 +334,11 @@ - printk(KERN_WARNING - " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->name); -+ up(&adapter->list); - return -ENOMEM; - } -- - adapter->clients[i] = client; -- adapter->client_count++; -+ up(&adapter->list); - - if (adapter->client_register) - if (adapter->client_register(client)) -@@ -431,16 +360,6 @@ - struct i2c_adapter *adapter = client->adapter; - int i,res; - -- for (i = 0; i < I2C_CLIENT_MAX; i++) -- if (client == adapter->clients[i]) -- break; -- if (I2C_CLIENT_MAX == i) { -- printk(KERN_WARNING " i2c-core.o: unregister_client " -- "[%s] not found\n", -- client->name); -- return -ENODEV; -- } -- - if( (client->flags & I2C_CLIENT_ALLOW_USE) && - (client->usage_count>0)) - return -EBUSY; -@@ -452,33 +371,41 @@ - return res; - } - -+ down(&adapter->list); -+ for (i = 0; i < I2C_CLIENT_MAX; i++) -+ if (client == adapter->clients[i]) -+ break; -+ if (I2C_CLIENT_MAX == i) { -+ printk(KERN_WARNING " i2c-core.o: unregister_client " -+ "[%s] not found\n", -+ client->name); -+ up(&adapter->list); -+ return -ENODEV; -+ } - adapter->clients[i] = NULL; -- adapter->client_count--; -+ up(&adapter->list); - - DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] unregistered.\n",client->name)); - return 0; - } - --void i2c_inc_use_client(struct i2c_client *client) -+static void i2c_inc_use_client(struct i2c_client *client) - { -- -- if (client->driver->inc_use != NULL) -- client->driver->inc_use(client); -- -- if (client->adapter->inc_use != NULL) -- client->adapter->inc_use(client->adapter); -+ if(client->driver->owner) -+ __MOD_INC_USE_COUNT(client->driver->owner); -+ if(client->adapter->owner) -+ __MOD_INC_USE_COUNT(client->adapter->owner); - } - --void i2c_dec_use_client(struct i2c_client *client) -+static void i2c_dec_use_client(struct i2c_client *client) - { -- -- if (client->driver->dec_use != NULL) -- client->driver->dec_use(client); -- -- if (client->adapter->dec_use != NULL) -- client->adapter->dec_use(client->adapter); -+ if(client->driver->owner) -+ __MOD_DEC_USE_COUNT(client->driver->owner); -+ if(client->adapter->owner) -+ __MOD_DEC_USE_COUNT(client->adapter->owner); - } - -+#if 0 /* just forget about this for now --km */ - struct i2c_client *i2c_get_client(int driver_id, int adapter_id, - struct i2c_client *prev) - { -@@ -545,18 +472,17 @@ - - return 0; - } -+#endif - - int i2c_use_client(struct i2c_client *client) - { -- if(client->flags & I2C_CLIENT_ALLOW_USE) { -- if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE) -+ if (client->flags & I2C_CLIENT_ALLOW_USE) { -+ if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE) -+ client->usage_count++; -+ else if (client->usage_count > 0) -+ return -EBUSY; -+ else - client->usage_count++; -- else { -- if(client->usage_count > 0) -- return -EBUSY; -- else -- client->usage_count++; -- } - } - - i2c_inc_use_client(client); -@@ -589,12 +515,13 @@ - #ifdef CONFIG_PROC_FS - - /* This function generates the output for /proc/bus/i2c */ --int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, -+static int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, - void *private) - { - int i; - int nr = 0; - /* Note that it is safe to write a `little' beyond len. Yes, really. */ -+ down(&core_lists); - for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++) - if (adapters[i]) { - nr += sprintf(buf+nr, "i2c-%d\t", i); -@@ -611,6 +538,7 @@ - adapters[i]->name, - adapters[i]->algo->name); - } -+ up(&core_lists); - return nr; - } - -@@ -621,98 +549,125 @@ - struct inode * inode = file->f_dentry->d_inode; - char *kbuf; - struct i2c_client *client; -+ struct i2c_adapter *adap; - int i,j,k,order_nr,len=0; - size_t len_total; - int order[I2C_CLIENT_MAX]; -+#define OUTPUT_LENGTH_PER_LINE 70 - -- if (count > 4000) -- return -EINVAL; - len_total = file->f_pos + count; -- /* Too bad if this gets longer (unlikely) */ -- if (len_total > 4000) -- len_total = 4000; -- for (i = 0; i < I2C_ADAP_MAX; i++) -- if (adapters[i]->inode == inode->i_ino) { -- /* We need a bit of slack in the kernel buffer; this makes the -- sprintf safe. */ -- if (! (kbuf = kmalloc(count + 80,GFP_KERNEL))) -- return -ENOMEM; -- /* Order will hold the indexes of the clients -- sorted by address */ -- order_nr=0; -- for (j = 0; j < I2C_CLIENT_MAX; j++) { -- if ((client = adapters[i]->clients[j]) && -- (client->driver->id != I2C_DRIVERID_I2CDEV)) { -- for(k = order_nr; -- (k > 0) && -- adapters[i]->clients[order[k-1]]-> -- addr > client->addr; -- k--) -- order[k] = order[k-1]; -- order[k] = j; -- order_nr++; -- } -- } -- -- -- for (j = 0; (j < order_nr) && (len < len_total); j++) { -- client = adapters[i]->clients[order[j]]; -- len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n", -- client->addr, -- client->name, -- client->driver->name); -- } -- len = len - file->f_pos; -- if (len > count) -- len = count; -- if (len < 0) -- len = 0; -- if (copy_to_user (buf,kbuf+file->f_pos, len)) { -- kfree(kbuf); -- return -EFAULT; -- } -- file->f_pos += len; -- kfree(kbuf); -- return len; -- } -- return -ENOENT; -+ if (len_total > (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE) ) -+ /* adjust to maximum file size */ -+ len_total = (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE); -+ -+ down(&core_lists); -+ /* adap = file->private_data; ?? --km */ -+ for (i = 0; i < I2C_ADAP_MAX; i++) { -+ adap = adapters[i]; -+ if (adap && (adap->inode == inode->i_ino)) -+ break; -+ } -+ if ( I2C_ADAP_MAX == i ) { -+ up(&core_lists); -+ return -ENOENT; -+ } -+ -+ /* We need a bit of slack in the kernel buffer; this makes the -+ sprintf safe. */ -+ if (! (kbuf = kmalloc(len_total + -+ OUTPUT_LENGTH_PER_LINE, -+ GFP_KERNEL))) -+ return -ENOMEM; -+ -+ /* Order will hold the indexes of the clients -+ sorted by address */ -+ order_nr=0; -+ down(&adap->list); -+ for (j = 0; j < I2C_CLIENT_MAX; j++) { -+ if ((client = adap->clients[j]) && -+ (client->driver->id != I2C_DRIVERID_I2CDEV)) { -+ for(k = order_nr; -+ (k > 0) && -+ adap->clients[order[k-1]]-> -+ addr > client->addr; -+ k--) -+ order[k] = order[k-1]; -+ order[k] = j; -+ order_nr++; -+ } -+ } -+ -+ -+ for (j = 0; (j < order_nr) && (len < len_total); j++) { -+ client = adap->clients[order[j]]; -+ len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n", -+ client->addr, -+ client->name, -+ client->driver->name); -+ } -+ up(&adap->list); -+ up(&core_lists); -+ -+ len = len - file->f_pos; -+ if (len > count) -+ len = count; -+ if (len < 0) -+ len = 0; -+ if (copy_to_user (buf,kbuf+file->f_pos, len)) { -+ kfree(kbuf); -+ return -EFAULT; -+ } -+ file->f_pos += len; -+ kfree(kbuf); -+ return len; -+} -+ -+static int i2cproc_register(struct i2c_adapter *adap, int bus) -+{ -+ char name[8]; -+ struct proc_dir_entry *proc_entry; -+ -+ sprintf(name,"i2c-%d", bus); -+ proc_entry = create_proc_entry(name,0,proc_bus); -+ if (! proc_entry) { -+ printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", -+ name); -+ return -ENOENT; -+ } -+ -+ proc_entry->proc_fops = &i2cproc_operations; -+ proc_entry->owner = adap->owner; -+ adap->inode = proc_entry->low_ino; -+ return 0; - } - --int i2cproc_init(void) -+static void i2cproc_remove(int bus) - { -+ char name[8]; -+ sprintf(name,"i2c-%d", bus); -+ remove_proc_entry(name, proc_bus); -+} - -+static int __init i2cproc_init(void) -+{ - struct proc_dir_entry *proc_bus_i2c; - -- i2cproc_initialized = 0; -- -- if (! proc_bus) { -- printk("i2c-core.o: /proc/bus/ does not exist"); -- i2cproc_cleanup(); -- return -ENOENT; -- } - proc_bus_i2c = create_proc_entry("i2c",0,proc_bus); - if (!proc_bus_i2c) { - printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c"); -- i2cproc_cleanup(); - return -ENOENT; - } -+ - proc_bus_i2c->read_proc = &read_bus_i2c; - proc_bus_i2c->owner = THIS_MODULE; -- i2cproc_initialized += 2; - return 0; - } - --int i2cproc_cleanup(void) -+static void __exit i2cproc_cleanup(void) - { -- -- if (i2cproc_initialized >= 1) { -- remove_proc_entry("i2c",proc_bus); -- i2cproc_initialized -= 2; -- } -- return 0; -+ remove_proc_entry("i2c",proc_bus); - } - -- - #endif /* def CONFIG_PROC_FS */ - - /* ---------------------------------------------------- -@@ -728,9 +683,9 @@ - DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n", - adap->name,num)); - -- I2C_LOCK(adap); -+ down(&adap->bus); - ret = adap->algo->master_xfer(adap,msgs,num); -- I2C_UNLOCK(adap); -+ up(&adap->bus); - - return ret; - } else { -@@ -755,9 +710,9 @@ - DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n", - count,client->adapter->name)); - -- I2C_LOCK(adap); -+ down(&adap->bus); - ret = adap->algo->master_xfer(adap,&msg,1); -- I2C_UNLOCK(adap); -+ up(&adap->bus); - - /* if everything went ok (i.e. 1 msg transmitted), return #bytes - * transmitted, else error code. -@@ -785,9 +740,9 @@ - DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n", - count,client->adapter->name)); - -- I2C_LOCK(adap); -+ down(&adap->bus); - ret = adap->algo->master_xfer(adap,&msg,1); -- I2C_UNLOCK(adap); -+ up(&adap->bus); - - DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n", - ret, count, client->addr)); -@@ -965,6 +920,123 @@ - - /* The SMBus parts */ - -+#define POLY (0x1070U << 3) -+static u8 -+crc8(u16 data) -+{ -+ int i; -+ -+ for(i = 0; i < 8; i++) { -+ if (data & 0x8000) -+ data = data ^ POLY; -+ data = data << 1; -+ } -+ return (u8)(data >> 8); -+} -+ -+/* CRC over count bytes in the first array plus the bytes in the rest -+ array if it is non-null. rest[0] is the (length of rest) - 1 -+ and is included. */ -+u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest) -+{ -+ int i; -+ -+ for(i = 0; i < count; i++) -+ crc = crc8((crc ^ first[i]) << 8); -+ if(rest != NULL) -+ for(i = 0; i <= rest[0]; i++) -+ crc = crc8((crc ^ rest[i]) << 8); -+ return crc; -+} -+ -+u8 i2c_smbus_pec(int count, u8 *first, u8 *rest) -+{ -+ return i2c_smbus_partial_pec(0, count, first, rest); -+} -+ -+/* Returns new "size" (transaction type) -+ Note that we convert byte to byte_data and byte_data to word_data -+ rather than invent new xxx_PEC transactions. */ -+int i2c_smbus_add_pec(u16 addr, u8 command, int size, -+ union i2c_smbus_data *data) -+{ -+ u8 buf[3]; -+ -+ buf[0] = addr << 1; -+ buf[1] = command; -+ switch(size) { -+ case I2C_SMBUS_BYTE: -+ data->byte = i2c_smbus_pec(2, buf, NULL); -+ size = I2C_SMBUS_BYTE_DATA; -+ break; -+ case I2C_SMBUS_BYTE_DATA: -+ buf[2] = data->byte; -+ data->word = buf[2] || -+ (i2c_smbus_pec(3, buf, NULL) << 8); -+ size = I2C_SMBUS_WORD_DATA; -+ break; -+ case I2C_SMBUS_WORD_DATA: -+ /* unsupported */ -+ break; -+ case I2C_SMBUS_BLOCK_DATA: -+ data->block[data->block[0] + 1] = -+ i2c_smbus_pec(2, buf, data->block); -+ size = I2C_SMBUS_BLOCK_DATA_PEC; -+ break; -+ } -+ return size; -+} -+ -+int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial, -+ union i2c_smbus_data *data) -+{ -+ u8 buf[3], rpec, cpec; -+ -+ buf[1] = command; -+ switch(size) { -+ case I2C_SMBUS_BYTE_DATA: -+ buf[0] = (addr << 1) | 1; -+ cpec = i2c_smbus_pec(2, buf, NULL); -+ rpec = data->byte; -+ break; -+ case I2C_SMBUS_WORD_DATA: -+ buf[0] = (addr << 1) | 1; -+ buf[2] = data->word & 0xff; -+ cpec = i2c_smbus_pec(3, buf, NULL); -+ rpec = data->word >> 8; -+ break; -+ case I2C_SMBUS_WORD_DATA_PEC: -+ /* unsupported */ -+ cpec = rpec = 0; -+ break; -+ case I2C_SMBUS_PROC_CALL_PEC: -+ /* unsupported */ -+ cpec = rpec = 0; -+ break; -+ case I2C_SMBUS_BLOCK_DATA_PEC: -+ buf[0] = (addr << 1); -+ buf[2] = (addr << 1) | 1; -+ cpec = i2c_smbus_pec(3, buf, data->block); -+ rpec = data->block[data->block[0] + 1]; -+ break; -+ case I2C_SMBUS_BLOCK_PROC_CALL_PEC: -+ buf[0] = (addr << 1) | 1; -+ rpec = i2c_smbus_partial_pec(partial, 1, -+ buf, data->block); -+ cpec = data->block[data->block[0] + 1]; -+ break; -+ default: -+ cpec = rpec = 0; -+ break; -+ } -+ if(rpec != cpec) { -+ DEB(printk(KERN_DEBUG "i2c-core.o: Bad PEC 0x%02x vs. 0x%02x\n", -+ rpec, cpec)); -+ return -1; -+ } -+ return 0; -+} -+ - extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value) - { - return i2c_smbus_xfer(client->adapter,client->addr,client->flags, -@@ -983,8 +1055,9 @@ - - extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value) - { -+ union i2c_smbus_data data; /* only for PEC */ - return i2c_smbus_xfer(client->adapter,client->addr,client->flags, -- I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL); -+ I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data); - } - - extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command) -@@ -1072,6 +1145,43 @@ - I2C_SMBUS_BLOCK_DATA,&data); - } - -+/* Returns the number of read bytes */ -+extern s32 i2c_smbus_block_process_call(struct i2c_client * client, -+ u8 command, u8 length, u8 *values) -+{ -+ union i2c_smbus_data data; -+ int i; -+ if (length > I2C_SMBUS_BLOCK_MAX - 1) -+ return -1; -+ data.block[0] = length; -+ for (i = 1; i <= length; i++) -+ data.block[i] = values[i-1]; -+ if(i2c_smbus_xfer(client->adapter,client->addr,client->flags, -+ I2C_SMBUS_WRITE, command, -+ I2C_SMBUS_BLOCK_PROC_CALL, &data)) -+ return -1; -+ for (i = 1; i <= data.block[0]; i++) -+ values[i-1] = data.block[i]; -+ return data.block[0]; -+} -+ -+/* Returns the number of read bytes */ -+extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, -+ u8 command, u8 *values) -+{ -+ union i2c_smbus_data data; -+ int i; -+ if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, -+ I2C_SMBUS_READ,command, -+ I2C_SMBUS_I2C_BLOCK_DATA,&data)) -+ return -1; -+ else { -+ for (i = 1; i <= data.block[0]; i++) -+ values[i-1] = data.block[i]; -+ return data.block[0]; -+ } -+} -+ - extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, - u8 command, u8 length, u8 *values) - { -@@ -1098,13 +1208,13 @@ - need to use only one message; when reading, we need two. We initialize - most things with sane defaults, to keep the code below somewhat - simpler. */ -- unsigned char msgbuf0[34]; -- unsigned char msgbuf1[34]; -+ unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+2]; -+ unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; - int num = read_write == I2C_SMBUS_READ?2:1; - struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, - { addr, flags | I2C_M_RD, 0, msgbuf1 } - }; -- int i; -+ int i, len; - - msgbuf0[0] = command; - switch(size) { -@@ -1140,16 +1250,30 @@ - break; - case I2C_SMBUS_PROC_CALL: - num = 2; /* Special case */ -+ read_write = I2C_SMBUS_READ; - msg[0].len = 3; - msg[1].len = 2; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; - break; - case I2C_SMBUS_BLOCK_DATA: -+ case I2C_SMBUS_BLOCK_DATA_PEC: - if (read_write == I2C_SMBUS_READ) { -- printk(KERN_ERR "i2c-core.o: Block read not supported " -- "under I2C emulation!\n"); -- return -1; -+ /* I2C_FUNC_SMBUS_EMUL doesn't include I2C_FUNC_SMBUS_READ_BLOCK_DATA */ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BLOCK_DATA)) { -+ printk(KERN_ERR "i2c-core.o: Block read not supported " -+ "under I2C emulation!\n"); -+ return -1; -+ } -+ /* set send message */ -+ msg[0].len = 1; -+ /* set recv message */ -+ msg[1].flags |= I2C_M_RECV_LEN; -+ msg[1].len = I2C_SMBUS_BLOCK_MAX + 1; -+ if (size == I2C_SMBUS_BLOCK_DATA_PEC) { -+ msg[1].len++; -+ msg[1].flags |= I2C_M_RECV_PEC; -+ } - } else { - msg[0].len = data->block[0] + 2; - if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { -@@ -1158,10 +1282,57 @@ - data->block[0]); - return -1; - } -+ if(size == I2C_SMBUS_BLOCK_DATA_PEC) -+ (msg[0].len)++; - for (i = 1; i <= msg[0].len; i++) - msgbuf0[i] = data->block[i-1]; - } - break; -+ case I2C_SMBUS_BLOCK_PROC_CALL: -+ case I2C_SMBUS_BLOCK_PROC_CALL_PEC: -+ /* I2C_FUNC_SMBUS_EMUL doesn't include I2C_FUNC_SMBUS_BLOCK_PROC_CALL */ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_PROC_CALL)) { -+ printk(KERN_ERR "i2c-core.o: adapter doesn't support block process call!\n"); -+ return -1; -+ } -+ -+ /* Another special case */ -+ num = 2; -+ read_write = I2C_SMBUS_READ; -+ -+ /* set send message */ -+ msg[0].len = data->block[0] + 2; -+ if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { -+ printk(KERN_ERR "i2c-core.o: smbus_access called with " -+ "invalid block write size (%d)\n", data->block[0]); -+ return -1; -+ } -+ for (i = 1; i <= msg[0].len; i++) -+ msgbuf0[i] = data->block[i-1]; -+ -+ /* set recv message */ -+ msg[1].flags |= I2C_M_RECV_LEN; -+ msg[1].len = I2C_SMBUS_BLOCK_MAX + 1; -+ if (size == I2C_SMBUS_BLOCK_PROC_CALL_PEC) { -+ msg[1].len++; -+ msg[1].flags |= I2C_M_RECV_PEC; -+ } -+ break; -+ case I2C_SMBUS_I2C_BLOCK_DATA: -+ if (read_write == I2C_SMBUS_READ) { -+ msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX; -+ } else { -+ msg[0].len = data->block[0] + 1; -+ if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) { -+ printk("i2c-core.o: i2c_smbus_xfer_emulated called with " -+ "invalid block write size (%d)\n", -+ data->block[0]); -+ return -1; -+ } -+ for (i = 1; i <= data->block[0]; i++) -+ msgbuf0[i] = data->block[i]; -+ } -+ break; - default: - printk(KERN_ERR "i2c-core.o: smbus_access called with invalid size (%d)\n", - size); -@@ -1183,25 +1354,72 @@ - case I2C_SMBUS_PROC_CALL: - data->word = msgbuf1[0] | (msgbuf1[1] << 8); - break; -+ case I2C_SMBUS_I2C_BLOCK_DATA: -+ /* fixed at 32 for now */ -+ data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX; -+ for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++) -+ data->block[i+1] = msgbuf1[i]; -+ break; -+ case I2C_SMBUS_BLOCK_DATA: -+ case I2C_SMBUS_BLOCK_PROC_CALL: -+ case I2C_SMBUS_BLOCK_DATA_PEC: -+ case I2C_SMBUS_BLOCK_PROC_CALL_PEC: -+ len = msgbuf1[0] + 1; -+ if(size == I2C_SMBUS_BLOCK_DATA_PEC || -+ size == I2C_SMBUS_BLOCK_PROC_CALL_PEC) -+ len++; -+ for (i = 0; i < len; i++) -+ data->block[i] = msgbuf1[i]; -+ break; - } - return 0; - } - - --s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, -+s32 i2c_smbus_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data * data) - { - s32 res; -- flags = flags & I2C_M_TEN; -- if (adapter->algo->smbus_xfer) { -- I2C_LOCK(adapter); -- res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, -+ int swpec = 0; -+ u8 partial = 0; -+ -+ flags &= I2C_M_TEN | I2C_CLIENT_PEC; -+ if((flags & I2C_CLIENT_PEC) && -+ !(i2c_check_functionality(adap, I2C_FUNC_SMBUS_HWPEC_CALC))) { -+ swpec = 1; -+ if(read_write == I2C_SMBUS_READ && -+ size == I2C_SMBUS_BLOCK_DATA) -+ size = I2C_SMBUS_BLOCK_DATA_PEC; -+ else if(size == I2C_SMBUS_PROC_CALL) -+ size = I2C_SMBUS_PROC_CALL_PEC; -+ else if(size == I2C_SMBUS_BLOCK_PROC_CALL) { -+ i2c_smbus_add_pec(addr, command, -+ I2C_SMBUS_BLOCK_DATA, data); -+ partial = data->block[data->block[0] + 1]; -+ size = I2C_SMBUS_BLOCK_PROC_CALL_PEC; -+ } else if(read_write == I2C_SMBUS_WRITE && -+ size != I2C_SMBUS_QUICK && -+ size != I2C_SMBUS_I2C_BLOCK_DATA) -+ size = i2c_smbus_add_pec(addr, command, size, data); -+ } -+ -+ if (adap->algo->smbus_xfer) { -+ down(&adap->bus); -+ res = adap->algo->smbus_xfer(adap,addr,flags,read_write, - command,size,data); -- I2C_UNLOCK(adapter); -+ up(&adap->bus); - } else -- res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, -+ res = i2c_smbus_xfer_emulated(adap,addr,flags,read_write, - command,size,data); -+ -+ if(res >= 0 && swpec && -+ size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA && -+ (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC || -+ size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) { -+ if(i2c_smbus_check_pec(addr, command, size, partial, data)) -+ return -1; -+ } - return res; - } - -@@ -1228,143 +1446,37 @@ - printk(KERN_INFO "i2c-core.o: i2c core module version %s (%s)\n", I2C_VERSION, I2C_DATE); - memset(adapters,0,sizeof(adapters)); - memset(drivers,0,sizeof(drivers)); -- adap_count=0; -- driver_count=0; - -- init_MUTEX(&adap_lock); -- init_MUTEX(&driver_lock); -- -- i2cproc_init(); -- -+#ifdef CONFIG_PROC_FS -+ return i2cproc_init(); -+#else - return 0; --} -- --#ifndef MODULE --#ifdef CONFIG_I2C_CHARDEV -- extern int i2c_dev_init(void); --#endif --#ifdef CONFIG_I2C_ALGOBIT -- extern int i2c_algo_bit_init(void); --#endif --#ifdef CONFIG_I2C_PHILIPSPAR -- extern int i2c_bitlp_init(void); --#endif --#ifdef CONFIG_I2C_ELV -- extern int i2c_bitelv_init(void); --#endif --#ifdef CONFIG_I2C_VELLEMAN -- extern int i2c_bitvelle_init(void); --#endif --#ifdef CONFIG_I2C_BITVIA -- extern int i2c_bitvia_init(void); --#endif -- --#ifdef CONFIG_I2C_ALGOPCF -- extern int i2c_algo_pcf_init(void); --#endif --#ifdef CONFIG_I2C_ELEKTOR -- extern int i2c_pcfisa_init(void); --#endif -- --#ifdef CONFIG_I2C_ALGO8XX -- extern int i2c_algo_8xx_init(void); --#endif --#ifdef CONFIG_I2C_RPXLITE -- extern int i2c_rpx_init(void); --#endif -- --#ifdef CONFIG_I2C_ALGO_SIBYTE -- extern int i2c_algo_sibyte_init(void); -- extern int i2c_sibyte_init(void); --#endif --#ifdef CONFIG_I2C_MAX1617 -- extern int i2c_max1617_init(void); --#endif --#ifdef CONFIG_I2C_ALGO_AU1550 -- extern int i2c_pb1550_init(void); - #endif -+} - --#ifdef CONFIG_I2C_PROC -- extern int sensors_init(void); -+static void __exit i2c_exit(void) -+{ -+#ifdef CONFIG_PROC_FS -+ i2cproc_cleanup(); - #endif -+} - --/* This is needed for automatic patch generation: sensors code starts here */ --/* This is needed for automatic patch generation: sensors code ends here */ -- -+/* leave this in for now simply to make patching easier so we don't have -+ to remove the call in drivers/char/mem.c */ - int __init i2c_init_all(void) - { -- /* --------------------- global ----- */ -- i2c_init(); -- --#ifdef CONFIG_I2C_CHARDEV -- i2c_dev_init(); --#endif -- /* --------------------- bit -------- */ --#ifdef CONFIG_I2C_ALGOBIT -- i2c_algo_bit_init(); --#endif --#ifdef CONFIG_I2C_PHILIPSPAR -- i2c_bitlp_init(); --#endif --#ifdef CONFIG_I2C_ELV -- i2c_bitelv_init(); --#endif --#ifdef CONFIG_I2C_VELLEMAN -- i2c_bitvelle_init(); --#endif -- -- /* --------------------- pcf -------- */ --#ifdef CONFIG_I2C_ALGOPCF -- i2c_algo_pcf_init(); --#endif --#ifdef CONFIG_I2C_ELEKTOR -- i2c_pcfisa_init(); --#endif -- -- /* --------------------- 8xx -------- */ --#ifdef CONFIG_I2C_ALGO8XX -- i2c_algo_8xx_init(); --#endif --#ifdef CONFIG_I2C_RPXLITE -- i2c_rpx_init(); --#endif -- -- /* --------------------- SiByte -------- */ --#ifdef CONFIG_I2C_ALGO_SIBYTE -- i2c_algo_sibyte_init(); -- i2c_sibyte_init(); --#endif --#ifdef CONFIG_I2C_MAX1617 -- i2c_max1617_init(); --#endif -- --#ifdef CONFIG_I2C_ALGO_AU1550 -- i2c_pb1550_init(); --#endif -- -- /* -------------- proc interface ---- */ --#ifdef CONFIG_I2C_PROC -- sensors_init(); --#endif --/* This is needed for automatic patch generation: sensors code starts here */ --/* This is needed for automatic patch generation: sensors code ends here */ -- - return 0; - } - --#endif -- -- -- - 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_inc_use_client); --EXPORT_SYMBOL(i2c_dec_use_client); -+#if 0 - EXPORT_SYMBOL(i2c_get_client); -+#endif - EXPORT_SYMBOL(i2c_use_client); - EXPORT_SYMBOL(i2c_release_client); - EXPORT_SYMBOL(i2c_check_addr); -@@ -1388,11 +1500,12 @@ - EXPORT_SYMBOL(i2c_smbus_process_call); - EXPORT_SYMBOL(i2c_smbus_read_block_data); - EXPORT_SYMBOL(i2c_smbus_write_block_data); -+EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); -+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); - - EXPORT_SYMBOL(i2c_get_functionality); - EXPORT_SYMBOL(i2c_check_functionality); - --#ifdef MODULE - MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); - MODULE_DESCRIPTION("I2C-Bus main module"); - MODULE_LICENSE("GPL"); -@@ -1400,13 +1513,5 @@ - MODULE_PARM(i2c_debug, "i"); - MODULE_PARM_DESC(i2c_debug,"debug level"); - --int init_module(void) --{ -- return i2c_init(); --} -- --void cleanup_module(void) --{ -- i2cproc_cleanup(); --} --#endif -+module_init(i2c_init); -+module_exit(i2c_exit); ---- linux-old/drivers/i2c/i2c-dev.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-dev.c Mon Dec 13 19:26:32 2004 -@@ -28,9 +28,8 @@ - /* The devfs code is contributed by Philipp Matthias Hahn - <pmhahn@titan.lahn.de> */ - --/* $Id: i2c-dev.c,v 1.40 2001/08/25 01:28:01 mds Exp $ */ -+/* $Id: i2c-dev.c,v 1.57 2003/12/22 20:03:39 khali Exp $ */ - --#include <linux/config.h> - #include <linux/kernel.h> - #include <linux/module.h> - #include <linux/fs.h> -@@ -39,21 +38,14 @@ - #ifdef CONFIG_DEVFS_FS - #include <linux/devfs_fs_kernel.h> - #endif -- -- --/* If you want debugging uncomment: */ --/* #define DEBUG */ -- - #include <linux/init.h> --#include <asm/uaccess.h> -- - #include <linux/i2c.h> - #include <linux/i2c-dev.h> -+#include <asm/uaccess.h> -+ -+/* If you want debugging uncomment: */ -+/* #define DEBUG */ - --#ifdef MODULE --extern int init_module(void); --extern int cleanup_module(void); --#endif /* def MODULE */ - - /* struct file_operations changed too often in the 2.1 series for nice code */ - -@@ -73,22 +65,14 @@ - static int i2cdev_command(struct i2c_client *client, unsigned int cmd, - void *arg); - --#ifdef MODULE --static --#else --extern --#endif -- int __init i2c_dev_init(void); --static int i2cdev_cleanup(void); -- - static struct file_operations i2cdev_fops = { -- owner: THIS_MODULE, -- llseek: no_llseek, -- read: i2cdev_read, -- write: i2cdev_write, -- ioctl: i2cdev_ioctl, -- open: i2cdev_open, -- release: i2cdev_release, -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = i2cdev_read, -+ .write = i2cdev_write, -+ .ioctl = i2cdev_ioctl, -+ .open = i2cdev_open, -+ .release = i2cdev_release, - }; - - #define I2CDEV_ADAPS_MAX I2C_ADAP_MAX -@@ -99,28 +83,22 @@ - #endif - - static struct i2c_driver i2cdev_driver = { -- name: "i2c-dev dummy driver", -- id: I2C_DRIVERID_I2CDEV, -- flags: I2C_DF_DUMMY, -- attach_adapter: i2cdev_attach_adapter, -- detach_client: i2cdev_detach_client, -- command: i2cdev_command, --/* inc_use: NULL, -- dec_use: NULL, */ -+ .owner = THIS_MODULE, /* not really used */ -+ .name = "i2c-dev dummy driver", -+ .id = I2C_DRIVERID_I2CDEV, -+ .flags = I2C_DF_DUMMY, -+ .attach_adapter = i2cdev_attach_adapter, -+ .detach_client = i2cdev_detach_client, -+ .command = i2cdev_command, - }; - - static struct i2c_client i2cdev_client_template = { -- name: "I2C /dev entry", -- id: 1, -- flags: 0, -- addr: -1, --/* adapter: NULL, */ -- driver: &i2cdev_driver, --/* data: NULL */ -+ .name = "I2C /dev entry", -+ .id = 1, -+ .addr = -1, -+ .driver = &i2cdev_driver, - }; - --static int i2cdev_initialized; -- - static ssize_t i2cdev_read (struct file *file, char *buf, size_t count, - loff_t *offset) - { -@@ -142,7 +120,7 @@ - return -ENOMEM; - - #ifdef DEBUG -- printk(KERN_DEBUG "i2c-dev.o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev), -+ printk(KERN_DEBUG "i2c-dev.o: i2c-%d reading %d bytes.\n",minor(inode->i_rdev), - count); - #endif - -@@ -177,7 +155,7 @@ - } - - #ifdef DEBUG -- printk(KERN_DEBUG "i2c-dev.o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev), -+ printk(KERN_DEBUG "i2c-dev.o: i2c-%d writing %d bytes.\n",minor(inode->i_rdev), - count); - #endif - ret = i2c_master_send(client,tmp,count); -@@ -199,7 +177,7 @@ - - #ifdef DEBUG - printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", -- MINOR(inode->i_rdev),cmd, arg); -+ minor(inode->i_rdev),cmd, arg); - #endif /* DEBUG */ - - switch ( cmd ) { -@@ -218,6 +196,12 @@ - else - client->flags &= ~I2C_M_TEN; - return 0; -+ case I2C_PEC: -+ if (arg) -+ client->flags |= I2C_CLIENT_PEC; -+ else -+ client->flags &= ~I2C_CLIENT_PEC; -+ return 0; - case I2C_FUNCS: - funcs = i2c_get_functionality(client->adapter); - return (copy_to_user((unsigned long *)arg,&funcs, -@@ -318,7 +302,8 @@ - (data_arg.size != I2C_SMBUS_WORD_DATA) && - (data_arg.size != I2C_SMBUS_PROC_CALL) && - (data_arg.size != I2C_SMBUS_BLOCK_DATA) && -- (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA)) { -+ (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && -+ (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { - #ifdef DEBUG - printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.size); -@@ -361,10 +346,11 @@ - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || - (data_arg.size == I2C_SMBUS_PROC_CALL)) - datasize = sizeof(data_arg.data->word); -- else /* size == I2C_SMBUS_BLOCK_DATA */ -+ else /* size == smbus block, i2c block, or block proc. call */ - datasize = sizeof(data_arg.data->block); - - if ((data_arg.size == I2C_SMBUS_PROC_CALL) || -+ (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_WRITE)) { - if (copy_from_user(&temp, data_arg.data, datasize)) - return -EFAULT; -@@ -373,6 +359,7 @@ - data_arg.read_write, - data_arg.command,data_arg.size,&temp); - if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || -+ (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_READ))) { - if (copy_to_user(data_arg.data, &temp, datasize)) - return -EFAULT; -@@ -387,7 +374,7 @@ - - int i2cdev_open (struct inode *inode, struct file *file) - { -- unsigned int minor = MINOR(inode->i_rdev); -+ unsigned int minor = minor(inode->i_rdev); - struct i2c_client *client; - - if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) { -@@ -403,11 +390,13 @@ - if(! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) - return -ENOMEM; - memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client)); -+ -+ /* registered with adapter, passed as client to user */ - client->adapter = i2cdev_adaps[minor]; - file->private_data = client; - -- if (i2cdev_adaps[minor]->inc_use) -- i2cdev_adaps[minor]->inc_use(i2cdev_adaps[minor]); -+ if(client->adapter->owner) -+ __MOD_INC_USE_COUNT(client->adapter->owner); - - #ifdef DEBUG - printk(KERN_DEBUG "i2c-dev.o: opened i2c-%d\n",minor); -@@ -417,16 +406,19 @@ - - static int i2cdev_release (struct inode *inode, struct file *file) - { -- unsigned int minor = MINOR(inode->i_rdev); -- kfree(file->private_data); -- file->private_data=NULL; -+ struct i2c_client *client; -+#ifdef DEBUG -+ unsigned int minor = minor(inode->i_rdev); -+#endif -+ -+ client = file->private_data; -+ file->private_data = NULL; -+ if(client->adapter->owner) -+ __MOD_DEC_USE_COUNT(client->adapter->owner); -+ kfree(client); - #ifdef DEBUG - printk(KERN_DEBUG "i2c-dev.o: Closed: i2c-%d\n", minor); - #endif -- lock_kernel(); -- if (i2cdev_adaps[minor]->dec_use) -- i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]); -- unlock_kernel(); - return 0; - } - -@@ -451,7 +443,7 @@ - devfs_i2c[i] = devfs_register (devfs_handle, name, - DEVFS_FL_DEFAULT, I2C_MAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, -- &i2cdev_fops, NULL); -+ &i2cdev_fops, adap); - #endif - printk(KERN_DEBUG "i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i); - } else { -@@ -479,13 +471,12 @@ - return -1; - } - --int __init i2c_dev_init(void) -+static int __init i2c_dev_init(void) - { - int res; - - printk(KERN_INFO "i2c-dev.o: i2c /dev entries driver module version %s (%s)\n", I2C_VERSION, I2C_DATE); - -- i2cdev_initialized = 0; - #ifdef CONFIG_DEVFS_FS - if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) { - #else -@@ -498,63 +489,31 @@ - #ifdef CONFIG_DEVFS_FS - devfs_handle = devfs_mk_dir(NULL, "i2c", NULL); - #endif -- i2cdev_initialized ++; -- - if ((res = i2c_add_driver(&i2cdev_driver))) { - printk(KERN_ERR "i2c-dev.o: Driver registration failed, module not inserted.\n"); -- i2cdev_cleanup(); -+#ifdef CONFIG_DEVFS_FS -+ devfs_unregister(devfs_handle); -+#endif -+ unregister_chrdev(I2C_MAJOR,"i2c"); - return res; - } -- i2cdev_initialized ++; - return 0; - } - --int i2cdev_cleanup(void) -+static void __exit i2c_dev_exit(void) - { -- int res; -- -- if (i2cdev_initialized >= 2) { -- if ((res = i2c_del_driver(&i2cdev_driver))) { -- printk("i2c-dev.o: Driver deregistration failed, " -- "module not removed.\n"); -- return res; -- } -- i2cdev_initialized --; -- } -- -- if (i2cdev_initialized >= 1) { -+ i2c_del_driver(&i2cdev_driver); - #ifdef CONFIG_DEVFS_FS -- devfs_unregister(devfs_handle); -- if ((res = devfs_unregister_chrdev(I2C_MAJOR, "i2c"))) { --#else -- if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) { -+ devfs_unregister(devfs_handle); - #endif -- printk("i2c-dev.o: unable to release major %d for i2c bus\n", -- I2C_MAJOR); -- return res; -- } -- i2cdev_initialized --; -- } -- return 0; -+ unregister_chrdev(I2C_MAJOR,"i2c"); - } - - EXPORT_NO_SYMBOLS; - --#ifdef MODULE -- - MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>"); - MODULE_DESCRIPTION("I2C /dev entries driver"); - MODULE_LICENSE("GPL"); - --int init_module(void) --{ -- return i2c_dev_init(); --} -- --int cleanup_module(void) --{ -- return i2cdev_cleanup(); --} -- --#endif /* def MODULE */ -- -+module_init(i2c_dev_init); -+module_exit(i2c_dev_exit); ---- linux-old/include/linux/i2c-dev.h Sat Jul 5 03:23:47 2003 -+++ linux/include/linux/i2c-dev.h Mon Dec 13 19:26:32 2004 -@@ -19,14 +19,16 @@ - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - --/* $Id: i2c-dev.h,v 1.9 2001/08/15 03:04:58 mds Exp $ */ -- --#ifndef I2C_DEV_H --#define I2C_DEV_H -+/* $Id: i2c-dev.h,v 1.14 2003/07/25 07:56:42 khali Exp $ */ - -+#ifndef _LINUX_I2C_DEV_H -+#define _LINUX_I2C_DEV_H - - #include <linux/types.h> --#include <linux/i2c.h> -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+#define minor(d) MINOR(d) -+#endif - - /* Some IOCTL commands are defined in <linux/i2c.h> */ - /* Note: 10-bit addresses are NOT supported! */ -@@ -45,137 +47,4 @@ - __u32 nmsgs; /* number of i2c_msgs */ - }; - --#ifndef __KERNEL__ -- --#include <sys/ioctl.h> -- --static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, -- int size, union i2c_smbus_data *data) --{ -- struct i2c_smbus_ioctl_data args; -- -- args.read_write = read_write; -- args.command = command; -- args.size = size; -- args.data = data; -- return ioctl(file,I2C_SMBUS,&args); --} -- -- --static inline __s32 i2c_smbus_write_quick(int file, __u8 value) --{ -- return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL); --} -- --static inline __s32 i2c_smbus_read_byte(int file) --{ -- union i2c_smbus_data data; -- if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data)) -- return -1; -- else -- return 0x0FF & data.byte; --} -- --static inline __s32 i2c_smbus_write_byte(int file, __u8 value) --{ -- return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, -- I2C_SMBUS_BYTE,NULL); --} -- --static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) --{ -- union i2c_smbus_data data; -- if (i2c_smbus_access(file,I2C_SMBUS_READ,command, -- I2C_SMBUS_BYTE_DATA,&data)) -- return -1; -- else -- return 0x0FF & data.byte; --} -- --static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, -- __u8 value) --{ -- union i2c_smbus_data data; -- data.byte = value; -- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, -- I2C_SMBUS_BYTE_DATA, &data); --} -- --static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) --{ -- union i2c_smbus_data data; -- if (i2c_smbus_access(file,I2C_SMBUS_READ,command, -- I2C_SMBUS_WORD_DATA,&data)) -- return -1; -- else -- return 0x0FFFF & data.word; --} -- --static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, -- __u16 value) --{ -- union i2c_smbus_data data; -- data.word = value; -- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, -- I2C_SMBUS_WORD_DATA, &data); --} -- --static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) --{ -- union i2c_smbus_data data; -- data.word = value; -- if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, -- I2C_SMBUS_PROC_CALL,&data)) -- return -1; -- else -- return 0x0FFFF & data.word; --} -- -- --/* Returns the number of read bytes */ --static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, -- __u8 *values) --{ -- union i2c_smbus_data data; -- int i; -- if (i2c_smbus_access(file,I2C_SMBUS_READ,command, -- I2C_SMBUS_BLOCK_DATA,&data)) -- return -1; -- else { -- for (i = 1; i <= data.block[0]; i++) -- values[i-1] = data.block[i]; -- return data.block[0]; -- } --} -- --static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, -- __u8 length, __u8 *values) --{ -- union i2c_smbus_data data; -- int i; -- if (length > 32) -- length = 32; -- for (i = 1; i <= length; i++) -- data.block[i] = values[i-1]; -- data.block[0] = length; -- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, -- I2C_SMBUS_BLOCK_DATA, &data); --} -- --static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, -- __u8 length, __u8 *values) --{ -- union i2c_smbus_data data; -- int i; -- if (length > 32) -- length = 32; -- for (i = 1; i <= length; i++) -- data.block[i] = values[i-1]; -- data.block[0] = length; -- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, -- I2C_SMBUS_I2C_BLOCK_DATA, &data); --} -- --#endif /* ndef __KERNEL__ */ -- --#endif -+#endif /* _LINUX_I2C_DEV_H */ ---- linux-old/drivers/i2c/i2c-elektor.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-elektor.c Mon Dec 13 19:26:33 2004 -@@ -31,23 +31,22 @@ - #include <linux/delay.h> - #include <linux/slab.h> - #include <linux/init.h> -+#include <linux/interrupt.h> - #include <linux/pci.h> --#include <asm/irq.h> --#include <asm/io.h> -- -+#include <linux/wait.h> - #include <linux/i2c.h> - #include <linux/i2c-algo-pcf.h> --#include <linux/i2c-elektor.h> --#include "i2c-pcf8584.h" -+#include <asm/io.h> -+#include <asm/irq.h> - - #define DEFAULT_BASE 0x330 - --static int base = 0; --static int irq = 0; -+static int base; -+static int irq; - static int clock = 0x1c; - static int own = 0x55; --static int mmapped = 0; --static int i2c_debug = 0; -+static int mmapped; -+static int i2c_debug; - - /* vdovikin: removed static struct i2c_pcf_isa gpi; code - - this module in real supports only one device, due to missing arguments -@@ -56,6 +55,7 @@ - - static wait_queue_head_t pcf_wait; - static int pcf_pending; -+static spinlock_t irq_driver_lock = SPIN_LOCK_UNLOCKED; - - /* ----- global defines ----------------------------------------------- */ - #define DEB(x) if (i2c_debug>=1) x -@@ -63,13 +63,24 @@ - #define DEB3(x) if (i2c_debug>=3) x - #define DEBE(x) x /* error messages */ - -+ -+/* compatibility */ -+#ifndef isa_readb -+#define isa_readb readb -+#endif -+ -+#ifndef isa_writeb -+#define isa_writeb writeb -+#endif -+ - /* ----- local functions ---------------------------------------------- */ - - static void pcf_isa_setbyte(void *data, int ctl, int val) - { - int address = ctl ? (base + 1) : base; - -- if (ctl && irq) { -+ /* enable irq if any specified for serial operation */ -+ if (ctl && irq && (val & I2C_PCF_ESO)) { - val |= I2C_PCF_ENI; - } - -@@ -81,10 +92,10 @@ - break; - case 2: /* double mapped I/O needed for UP2000 board, - I don't know why this... */ -- writeb(val, address); -+ isa_writeb(val, address); - /* fall */ - case 1: /* memory mapped I/O */ -- writeb(val, address); -+ isa_writeb(val, address); - break; - } - } -@@ -92,7 +103,7 @@ - static int pcf_isa_getbyte(void *data, int ctl) - { - int address = ctl ? (base + 1) : base; -- int val = mmapped ? readb(address) : inb(address); -+ int val = mmapped ? isa_readb(address) : inb(address); - - DEB3(printk(KERN_DEBUG "i2c-elektor.o: Read 0x%X 0x%02X\n", address, val)); - -@@ -115,12 +126,12 @@ - int timeout = 2; - - if (irq > 0) { -- cli(); -+ spin_lock_irq(&irq_driver_lock); - if (pcf_pending == 0) { - interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ ); - } else - pcf_pending = 0; -- sti(); -+ spin_unlock_irq(&irq_driver_lock); - } else { - udelay(100); - } -@@ -136,13 +147,11 @@ - static int pcf_isa_init(void) - { - if (!mmapped) { -- if (check_region(base, 2) < 0 ) { -+ if (!request_region(base, 2, "i2c (isa bus adapter)")) { - printk(KERN_ERR - "i2c-elektor.o: requested I/O region (0x%X:2) " - "is in use.\n", base); - return -ENODEV; -- } else { -- request_region(base, 2, "i2c (isa bus adapter)"); - } - } - if (irq > 0) { -@@ -156,70 +165,29 @@ - } - - --static void __exit pcf_isa_exit(void) --{ -- if (irq > 0) { -- disable_irq(irq); -- free_irq(irq, 0); -- } -- if (!mmapped) { -- release_region(base , 2); -- } --} -- -- --static int pcf_isa_reg(struct i2c_client *client) --{ -- return 0; --} -- -- --static int pcf_isa_unreg(struct i2c_client *client) --{ -- return 0; --} -- --static void pcf_isa_inc_use(struct i2c_adapter *adap) --{ --#ifdef MODULE -- MOD_INC_USE_COUNT; --#endif --} -- --static void pcf_isa_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_pcf_data pcf_isa_data = { -- NULL, -- pcf_isa_setbyte, -- pcf_isa_getbyte, -- pcf_isa_getown, -- pcf_isa_getclock, -- pcf_isa_waitforpin, -- 10, 10, 100, /* waits, timeout */ -+ .setpcf = pcf_isa_setbyte, -+ .getpcf = pcf_isa_getbyte, -+ .getown = pcf_isa_getown, -+ .getclock = pcf_isa_getclock, -+ .waitforpin = pcf_isa_waitforpin, -+ .udelay = 10, -+ .mdelay = 10, -+ .timeout = HZ, - }; - - static struct i2c_adapter pcf_isa_ops = { -- "PCF8584 ISA adapter", -- I2C_HW_P_ELEK, -- NULL, -- &pcf_isa_data, -- pcf_isa_inc_use, -- pcf_isa_dec_use, -- pcf_isa_reg, -- pcf_isa_unreg, -+ .owner = THIS_MODULE, -+ .name = "PCF8584 ISA adapter", -+ .id = I2C_HW_P_ELEK, -+ .algo_data = &pcf_isa_data, - }; - --int __init i2c_pcfisa_init(void) -+static int __init i2c_pcfisa_init(void) - { - #ifdef __alpha__ - /* check to see we have memory mapped PCF8584 connected to the -@@ -277,22 +245,41 @@ - } - - init_waitqueue_head(&pcf_wait); -- if (pcf_isa_init() == 0) { -- if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) -- return -ENODEV; -- } else { -+ if (pcf_isa_init()) - return -ENODEV; -- } -+ if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) -+ goto fail; - - printk(KERN_DEBUG "i2c-elektor.o: found device at %#x.\n", base); - - return 0; -+ -+ fail: -+ if (irq > 0) { -+ disable_irq(irq); -+ free_irq(irq, 0); -+ } -+ -+ if (!mmapped) -+ release_region(base , 2); -+ return -ENODEV; - } - -+static void __exit i2c_pcfisa_exit(void) -+{ -+ i2c_pcf_del_bus(&pcf_isa_ops); -+ -+ if (irq > 0) { -+ disable_irq(irq); -+ free_irq(irq, 0); -+ } -+ -+ if (!mmapped) -+ release_region(base , 2); -+} - - EXPORT_NO_SYMBOLS; - --#ifdef MODULE - MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); - MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); - MODULE_LICENSE("GPL"); -@@ -304,15 +291,5 @@ - MODULE_PARM(mmapped, "i"); - MODULE_PARM(i2c_debug, "i"); - --int init_module(void) --{ -- return i2c_pcfisa_init(); --} -- --void cleanup_module(void) --{ -- i2c_pcf_del_bus(&pcf_isa_ops); -- pcf_isa_exit(); --} -- --#endif -+module_init(i2c_pcfisa_init); -+module_exit(i2c_pcfisa_exit); ---- linux-old/include/linux/i2c-elektor.h Tue Nov 6 00:55:29 2001 -+++ linux/include/linux/i2c-elektor.h Mon Dec 13 19:26:33 2004 -@@ -1,47 +0,0 @@ --/* ------------------------------------------------------------------------- */ --/* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes */ --/* ------------------------------------------------------------------------- */ --/* Copyright (C) 1995-97 Simon G. Vogl -- 1998-99 Hans Berglund -- -- 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 <kmalkki@cc.hut.fi> and even -- Frodo Looijaard <frodol@dds.nl> */ -- --/* $Id: i2c-elektor.h,v 1.5 2001/06/05 01:46:33 mds Exp $ */ -- --#ifndef I2C_PCF_ELEKTOR_H --#define I2C_PCF_ELEKTOR_H 1 -- --/* -- * This struct contains the hw-dependent functions of PCF8584 adapters to -- * manipulate the registers, and to init any hw-specific features. -- * vdovikin: removed: this module in real supports only one device, -- * due to missing arguments in some functions, called from the algo-pcf module. -- * Sometimes it's need to be rewriten - -- * but for now just remove this for simpler reading */ -- --/* --struct i2c_pcf_isa { -- int pi_base; -- int pi_irq; -- int pi_clock; -- int pi_own; --}; --*/ -- --#endif /* PCF_ELEKTOR_H */ ---- linux-old/drivers/i2c/i2c-elv.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-elv.c Mon Dec 13 19:26:33 2004 -@@ -21,21 +21,18 @@ - /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even - Frodo Looijaard <frodol@dds.nl> */ - --/* $Id: i2c-elv.c,v 1.17 2001/07/29 02:44:25 mds Exp $ */ -+/* $Id: i2c-elv.c,v 1.29 2003/12/22 20:03:11 khali Exp $ */ - - #include <linux/kernel.h> - #include <linux/module.h> - #include <linux/delay.h> - #include <linux/slab.h> - #include <linux/init.h> -- --#include <asm/uaccess.h> -- - #include <linux/ioport.h> --#include <asm/io.h> - #include <linux/errno.h> - #include <linux/i2c.h> - #include <linux/i2c-algo-bit.h> -+#include <asm/io.h> - - #define DEFAULT_BASE 0x378 - static int base=0; -@@ -89,58 +86,31 @@ - - static int bit_elv_init(void) - { -- if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) { -- return -ENODEV; -- } else { -- /* test for ELV adap. */ -- if (inb(base+1) & 0x80) { /* BUSY should be high */ -- DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n")); -- return -ENODEV; -- } else { -- outb(0x0c,base+2); /* SLCT auf low */ -- udelay(400); -- if ( !(inb(base+1) && 0x10) ) { -- outb(0x04,base+2); -- DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n")); -- return -ENODEV; -- } -- } -- request_region(base,(base == 0x3bc)? 3 : 8, -- "i2c (ELV adapter)"); -- PortData = 0; -- bit_elv_setsda((void*)base,1); -- bit_elv_setscl((void*)base,1); -+ if (!request_region(base, (base == 0x3bc) ? 3 : 8, -+ "i2c (ELV adapter)")) -+ return -ENODEV; -+ -+ if (inb(base+1) & 0x80) { /* BUSY should be high */ -+ DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n")); -+ goto fail; -+ } -+ -+ outb(0x0c,base+2); /* SLCT auf low */ -+ udelay(400); -+ if (!(inb(base+1) && 0x10)) { -+ outb(0x04,base+2); -+ DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n")); -+ goto fail; - } -- return 0; --} -- --static void __exit bit_elv_exit(void) --{ -- release_region( base , (base == 0x3bc)? 3 : 8 ); --} -- --static int bit_elv_reg(struct i2c_client *client) --{ -- return 0; --} - --static int bit_elv_unreg(struct i2c_client *client) --{ -+ PortData = 0; -+ bit_elv_setsda((void*)base,1); -+ bit_elv_setscl((void*)base,1); - return 0; --} - --static void bit_elv_inc_use(struct i2c_adapter *adap) --{ --#ifdef MODULE -- MOD_INC_USE_COUNT; --#endif --} -- --static void bit_elv_dec_use(struct i2c_adapter *adap) --{ --#ifdef MODULE -- MOD_DEC_USE_COUNT; --#endif -+fail: -+ release_region(base , (base == 0x3bc) ? 3 : 8); -+ return -ENODEV; - } - - /* ------------------------------------------------------------------------ -@@ -148,26 +118,23 @@ - * This is only done when more than one hardware adapter is supported. - */ - static struct i2c_algo_bit_data bit_elv_data = { -- NULL, -- bit_elv_setsda, -- bit_elv_setscl, -- bit_elv_getsda, -- bit_elv_getscl, -- 80, 80, 100, /* waits, timeout */ -+ .setsda = bit_elv_setsda, -+ .setscl = bit_elv_setscl, -+ .getsda = bit_elv_getsda, -+ .getscl = bit_elv_getscl, -+ .udelay = 80, -+ .mdelay = 80, -+ .timeout = HZ - }; - - static struct i2c_adapter bit_elv_ops = { -- "ELV Parallel port adaptor", -- I2C_HW_B_ELV, -- NULL, -- &bit_elv_data, -- bit_elv_inc_use, -- bit_elv_dec_use, -- bit_elv_reg, -- bit_elv_unreg, -+ .owner = THIS_MODULE, -+ .name = "ELV Parallel port adaptor", -+ .id = I2C_HW_B_ELV, -+ .algo_data = &bit_elv_data, - }; - --int __init i2c_bitelv_init(void) -+static int __init i2c_bitelv_init(void) - { - printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - if (base==0) { -@@ -193,25 +160,19 @@ - return 0; - } - -+static void __exit i2c_bitelv_exit(void) -+{ -+ i2c_bit_del_bus(&bit_elv_ops); -+ release_region(base, (base == 0x3bc) ? 3 : 8); -+} - - EXPORT_NO_SYMBOLS; - --#ifdef MODULE - MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); - MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter"); - MODULE_LICENSE("GPL"); - - MODULE_PARM(base, "i"); - --int init_module(void) --{ -- return i2c_bitelv_init(); --} -- --void cleanup_module(void) --{ -- i2c_bit_del_bus(&bit_elv_ops); -- bit_elv_exit(); --} -- --#endif -+module_init(i2c_bitelv_init); -+module_exit(i2c_bitelv_exit); ---- linux-old/drivers/i2c/i2c-frodo.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-frodo.c Mon Dec 13 19:26:33 2004 -@@ -0,0 +1,83 @@ -+ -+/* -+ * linux/drivers/i2c/i2c-frodo.c -+ * -+ * Author: Abraham van der Merwe <abraham@2d3d.co.za> -+ * -+ * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 -+ * Development board (Frodo). -+ * -+ * This source code is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-bit.h> -+#include <asm/hardware.h> -+ -+ -+static void frodo_setsda (void *data,int state) -+{ -+ if (state) -+ FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; -+ else -+ FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; -+} -+ -+static void frodo_setscl (void *data,int state) -+{ -+ if (state) -+ FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; -+ else -+ FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; -+} -+ -+static int frodo_getsda (void *data) -+{ -+ return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); -+} -+ -+static int frodo_getscl (void *data) -+{ -+ return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); -+} -+ -+static struct i2c_algo_bit_data bit_frodo_data = { -+ .setsda = frodo_setsda, -+ .setscl = frodo_setscl, -+ .getsda = frodo_getsda, -+ .getscl = frodo_getscl, -+ .udelay = 80, -+ .mdelay = 80, -+ .timeout = HZ -+}; -+ -+static struct i2c_adapter frodo_ops = { -+ .owner = THIS_MODULE, -+ .name = "Frodo adapter driver", -+ .id = I2C_HW_B_FRODO, -+ .algo_data = &bit_frodo_data, -+}; -+ -+static int __init i2c_frodo_init (void) -+{ -+ return i2c_bit_add_bus(&frodo_ops); -+} -+ -+static void __exit i2c_frodo_exit (void) -+{ -+ i2c_bit_del_bus(&frodo_ops); -+} -+ -+MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>"); -+MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); -+MODULE_LICENSE ("GPL"); -+ -+module_init (i2c_frodo_init); -+module_exit (i2c_frodo_exit); -+ ---- linux-old/include/linux/i2c-id.h Wed Jul 7 00:38:02 2004 -+++ linux/include/linux/i2c-id.h Mon Dec 13 19:26:33 2004 -@@ -20,10 +20,11 @@ - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* ------------------------------------------------------------------------- */ - --/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */ -+/* $Id: i2c-id.h,v 1.92 2004/07/27 18:15:06 mmh Exp $ */ -+ -+#ifndef LINUX_I2C_ID_H -+#define LINUX_I2C_ID_H - --#ifndef I2C_ID_H --#define I2C_ID_H - /* - * This file is part of the i2c-bus package and contains the identifier - * values for drivers, adapters and other folk populating these serial -@@ -90,10 +91,25 @@ - #define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */ - #define I2C_DRIVERID_SP5055 44 /* Satellite tuner */ - #define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */ -+#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */ -+#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */ - #define I2C_DRIVERID_ADV7175 48 /* ADV 7175/7176 video encoder */ --#define I2C_DRIVERID_MAX1617 56 /* temp sensor */ --#define I2C_DRIVERID_SAA7191 57 /* video decoder */ --#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ -+#define I2C_DRIVERID_ZR36067 49 /* Zoran 36067 video encoder */ -+#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */ -+#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */ -+#define I2C_DRIVERID_STM41T00 52 /* real time clock */ -+#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */ -+#define I2C_DRIVERID_ADV7170 54 /* video encoder */ -+#define I2C_DRIVERID_RADEON 55 /* I2C bus on Radeon boards */ -+#define I2C_DRIVERID_MAX1617 56 /* temp sensor */ -+#define I2C_DRIVERID_SAA7191 57 /* video encoder */ -+#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ -+#define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */ -+#define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */ -+#define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */ -+#define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */ -+#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ -+ - - #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ - #define I2C_DRIVERID_EXP1 0xF1 -@@ -102,6 +118,8 @@ - - #define I2C_DRIVERID_I2CDEV 900 - #define I2C_DRIVERID_I2CPROC 901 -+#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ -+#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */ - - /* IDs -- Use DRIVERIDs 1000-1999 for sensors. - These were originally in sensors.h in the lm_sensors package */ -@@ -131,6 +149,28 @@ - #define I2C_DRIVERID_ADM1024 1025 - #define I2C_DRIVERID_IT87 1026 - #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */ -+#define I2C_DRIVERID_FSCPOS 1028 -+#define I2C_DRIVERID_FSCSCY 1029 -+#define I2C_DRIVERID_PCF8591 1030 -+#define I2C_DRIVERID_SMSC47M1 1031 -+#define I2C_DRIVERID_VT1211 1032 -+#define I2C_DRIVERID_LM92 1033 -+#define I2C_DRIVERID_VT8231 1034 -+#define I2C_DRIVERID_SMARTBATT 1035 -+#define I2C_DRIVERID_BMCSENSORS 1036 -+#define I2C_DRIVERID_FS451 1037 -+#define I2C_DRIVERID_W83627HF 1038 -+#define I2C_DRIVERID_LM85 1039 -+#define I2C_DRIVERID_LM83 1040 -+#define I2C_DRIVERID_SAA1064 1041 -+#define I2C_DRIVERID_LM90 1042 -+#define I2C_DRIVERID_ASB100 1043 -+#define I2C_DRIVERID_MAX6650 1044 -+#define I2C_DRIVERID_XEONTEMP 1045 -+#define I2C_DRIVERID_FSCHER 1046 -+#define I2C_DRIVERID_W83L785TS 1047 -+#define I2C_DRIVERID_ADM1026 1048 -+#define I2C_DRIVERID_LM93 1049 - - /* - * ---- Adapter types ---------------------------------------------------- -@@ -147,16 +187,21 @@ - #define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */ - #define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */ - #define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */ -- -+#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */ -+#define I2C_ALGO_SAA7134 0x090000 -+#define I2C_ALGO_MPC824X 0x0a0000 /* Motorola 8240 / 8245 */ -+#define I2C_ALGO_IPMI 0x0b0000 /* IPMI dummy adapter */ -+#define I2C_ALGO_IPMB 0x0c0000 /* IPMB adapter */ -+#define I2C_ALGO_MPC107 0x0d0000 - #define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */ - - #define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */ -- --#define I2C_ALGO_SIBYTE 0x120000 /* Broadcom SiByte SOCs */ -- --#define I2C_ALGO_SGI 0x130000 /* SGI algorithm */ -- --#define I2C_ALGO_AU1550 0x140000 /* Alchemy Au1550 PSC */ -+#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */ -+#define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */ -+#define I2C_ALGO_OCP_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */ -+#define I2C_ALGO_SIBYTE 0x150000 /* Broadcom SiByte SOCs */ -+#define I2C_ALGO_SGI 0x160000 /* SGI algorithm */ -+#define I2C_ALGO_USB 0x170000 /* USB algorithm */ - - #define I2C_ALGO_EXP 0x800000 /* experimental */ - -@@ -184,21 +229,46 @@ - #define I2C_HW_B_I810 0x0a /* Intel I810 */ - #define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */ - #define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */ -+#define I2C_HW_B_SAVG 0x0d /* Savage 4 */ -+#define I2C_HW_B_SCX200 0x0e /* Nat'l Semi SCx200 I2C */ - #define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */ - #define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */ - #define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */ -+#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */ -+#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface (ARM) */ -+#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */ -+#define I2C_HW_B_IXP2000 0x16 /* GPIO on IXP2000 systems */ -+#define I2C_HW_B_IXP425 0x17 /* GPIO on IXP425 systems */ -+#define I2C_HW_B_S3VIA 0x18 /* S3Via ProSavage adapter */ -+#define I2C_HW_B_ZR36067 0x19 /* Zoran-36057/36067 based boards */ -+#define I2C_HW_B_PCILYNX 0x1a /* TI PCILynx I2C adapter */ - - /* --- PCF 8584 based algorithms */ - #define I2C_HW_P_LP 0x00 /* Parallel port interface */ - #define I2C_HW_P_ISA 0x01 /* generic ISA Bus inteface card */ - #define I2C_HW_P_ELEK 0x02 /* Elektor ISA Bus inteface card */ - -+/* --- USB based adapters */ -+#define I2C_HW_USB_USBVISION 0x00 -+ - /* --- ACPI Embedded controller algorithms */ - #define I2C_HW_ACPI_EC 0x00 - -+/* --- MPC824x PowerPC adapters */ -+#define I2C_HW_MPC824X 0x00 /* Motorola 8240 / 8245 */ -+ - /* --- MPC8xx PowerPC adapters */ - #define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */ - -+/* --- ITE based algorithms */ -+#define I2C_HW_I_IIC 0x00 /* controller on the ITE */ -+ -+/* --- PowerPC on-chip adapters */ -+#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */ -+ -+/* --- XSCALE on-chip adapters */ -+#define I2C_HW_IOP321 0x00 -+ - /* --- Broadcom SiByte adapters */ - #define I2C_HW_SIBYTE 0x00 - -@@ -206,9 +276,6 @@ - #define I2C_HW_SGI_VINO 0x00 - #define I2C_HW_SGI_MACE 0x01 - --/* --- Au1550 PSC adapters */ --#define I2C_HW_AU1550_PSC 0x00 -- - /* --- SMBus only adapters */ - #define I2C_HW_SMBUS_PIIX4 0x00 - #define I2C_HW_SMBUS_ALI15X3 0x01 -@@ -218,9 +285,27 @@ - #define I2C_HW_SMBUS_AMD756 0x05 - #define I2C_HW_SMBUS_SIS5595 0x06 - #define I2C_HW_SMBUS_ALI1535 0x07 -+#define I2C_HW_SMBUS_SIS630 0x08 -+#define I2C_HW_SMBUS_SIS645 0x09 -+#define I2C_HW_SMBUS_AMD8111 0x0a -+#define I2C_HW_SMBUS_SCX200 0x0b -+#define I2C_HW_SMBUS_NFORCE2 0x0c - #define I2C_HW_SMBUS_W9968CF 0x0d -+#define I2C_HW_SMBUS_OV511 0x0e /* OV511(+) USB 1.1 webcam ICs */ -+#define I2C_HW_SMBUS_OV518 0x0f /* OV518(+) USB 1.1 webcam ICs */ -+#define I2C_HW_SMBUS_OV519 0x10 /* OV519 USB 1.1 webcam IC */ -+#define I2C_HW_SMBUS_OVFX2 0x11 /* Cypress/OmniVision FX2 webcam */ - - /* --- ISA pseudo-adapter */ - #define I2C_HW_ISA 0x00 - --#endif /* I2C_ID_H */ -+/* --- IPMI pseudo-adapter */ -+#define I2C_HW_IPMI 0x00 -+ -+/* --- IPMB adapter */ -+#define I2C_HW_IPMB 0x00 -+ -+/* --- MCP107 adapter */ -+#define I2C_HW_MPC107 0x00 -+ -+#endif /* LINUX_I2C_ID_H */ ---- linux-old/drivers/i2c/i2c-pcf-epp.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-pcf-epp.c Mon Dec 13 19:26:34 2004 -@@ -0,0 +1,281 @@ -+/* ------------------------------------------------------------------------- */ -+/* i2c-pcf-epp.c i2c-hw access for PCF8584 style EPP parallel port adapters */ -+/* ------------------------------------------------------------------------- */ -+/* Copyright (C) 1998-99 Hans Berglund -+ -+ 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 Ryosuke Tajima <rosk@jsk.t.u-tokyo.ac.jp> */ -+ -+#include <linux/kernel.h> -+#include <linux/ioport.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/parport.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-pcf.h> -+#include <asm/irq.h> -+#include <asm/io.h> -+ -+ -+struct i2c_pcf_epp { -+ int pe_base; -+ int pe_irq; -+ int pe_clock; -+ int pe_own; -+} ; -+ -+#define DEFAULT_BASE 0x378 -+#define DEFAULT_IRQ 7 -+#define DEFAULT_CLOCK 0x1c -+#define DEFAULT_OWN 0x55 -+ -+static int base = 0; -+static int irq = 0; -+static int clock = 0; -+static int own = 0; -+static int i2c_debug=0; -+static struct i2c_pcf_epp gpe; -+static wait_queue_head_t pcf_wait; -+static int pcf_pending; -+static spinlock_t irq_driver_lock = SPIN_LOCK_UNLOCKED; -+ -+/* ----- global defines ----------------------------------------------- */ -+#define DEB(x) if (i2c_debug>=1) x -+#define DEB2(x) if (i2c_debug>=2) x -+#define DEB3(x) if (i2c_debug>=3) x -+#define DEBE(x) x /* error messages */ -+ -+/* --- Convenience defines for the EPP/SPP port: */ -+#define BASE ((struct i2c_pcf_epp *)(data))->pe_base -+// #define DATA BASE /* SPP data port */ -+#define STAT (BASE+1) /* SPP status port */ -+#define CTRL (BASE+2) /* SPP control port */ -+#define EADD (BASE+3) /* EPP address port */ -+#define EDAT (BASE+4) /* EPP data port */ -+ -+/* ----- local functions ---------------------------------------------- */ -+ -+static void pcf_epp_setbyte(void *data, int ctl, int val) -+{ -+ if (ctl) { -+ if (gpe.pe_irq > 0) { -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: Write control 0x%x\n", -+ val|I2C_PCF_ENI)); -+ // set A0 pin HIGH -+ outb(inb(CTRL) | PARPORT_CONTROL_INIT, CTRL); -+ // DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: CTRL port = 0x%x\n", inb(CTRL))); -+ // DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: STAT port = 0x%x\n", inb(STAT))); -+ -+ // EPP write data cycle -+ outb(val | I2C_PCF_ENI, EDAT); -+ } else { -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: Write control 0x%x\n", val)); -+ // set A0 pin HIGH -+ outb(inb(CTRL) | PARPORT_CONTROL_INIT, CTRL); -+ outb(val, CTRL); -+ } -+ } else { -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: Write data 0x%x\n", val)); -+ // set A0 pin LO -+ outb(inb(CTRL) & ~PARPORT_CONTROL_INIT, CTRL); -+ // DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: CTRL port = 0x%x\n", inb(CTRL))); -+ // DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: STAT port = 0x%x\n", inb(STAT))); -+ outb(val, EDAT); -+ } -+} -+ -+static int pcf_epp_getbyte(void *data, int ctl) -+{ -+ int val; -+ -+ if (ctl) { -+ // set A0 pin HIGH -+ outb(inb(CTRL) | PARPORT_CONTROL_INIT, CTRL); -+ val = inb(EDAT); -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: Read control 0x%x\n", val)); -+ } else { -+ // set A0 pin LOW -+ outb(inb(CTRL) & ~PARPORT_CONTROL_INIT, CTRL); -+ val = inb(EDAT); -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: Read data 0x%x\n", val)); -+ } -+ return (val); -+} -+ -+static int pcf_epp_getown(void *data) -+{ -+ return (gpe.pe_own); -+} -+ -+ -+static int pcf_epp_getclock(void *data) -+{ -+ return (gpe.pe_clock); -+} -+ -+#if 0 -+static void pcf_epp_sleep(unsigned long timeout) -+{ -+ schedule_timeout( timeout * HZ); -+} -+#endif -+ -+static void pcf_epp_waitforpin(void) { -+ int timeout = 10; -+ -+ if (gpe.pe_irq > 0) { -+ spin_lock_irq(&irq_driver_lock); -+ if (pcf_pending == 0) { -+ interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ); -+ //udelay(100); -+ } else { -+ pcf_pending = 0; -+ } -+ spin_unlock_irq(&irq_driver_lock); -+ } else { -+ udelay(100); -+ } -+} -+ -+static void pcf_epp_handler(int this_irq, void *dev_id, struct pt_regs *regs) { -+ pcf_pending = 1; -+ wake_up_interruptible(&pcf_wait); -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: in interrupt handler.\n")); -+} -+ -+ -+static int pcf_epp_init(void *data) -+{ -+ if (check_region(gpe.pe_base, 5) < 0 ) { -+ -+ printk(KERN_WARNING "Could not request port region with base 0x%x\n", gpe.pe_base); -+ return -ENODEV; -+ } else { -+ request_region(gpe.pe_base, 5, "i2c (EPP parallel port adapter)"); -+ } -+ -+ DEB3(printk(KERN_DEBUG "i2c-pcf-epp.o: init status port = 0x%x\n", inb(0x379))); -+ -+ if (gpe.pe_irq > 0) { -+ if (request_irq(gpe.pe_irq, pcf_epp_handler, 0, "PCF8584", 0) < 0) { -+ printk(KERN_NOTICE "i2c-pcf-epp.o: Request irq%d failed\n", gpe.pe_irq); -+ gpe.pe_irq = 0; -+ } else -+ disable_irq(gpe.pe_irq); -+ enable_irq(gpe.pe_irq); -+ } -+ // EPP mode initialize -+ // enable interrupt from nINTR pin -+ outb(inb(CTRL)|0x14, CTRL); -+ // clear ERROR bit of STAT -+ outb(inb(STAT)|0x01, STAT); -+ outb(inb(STAT)&~0x01,STAT); -+ -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------ -+ * 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_pcf_data pcf_epp_data = { -+ .setpcf = pcf_epp_setbyte, -+ .getpcf = pcf_epp_getbyte, -+ .getown = pcf_epp_getown, -+ .getclock = pcf_epp_getclock, -+ .waitforpin = pcf_epp_waitforpin, -+ .udelay = 80, -+ .mdelay = 80, -+ .timeout = HZ, -+}; -+ -+static struct i2c_adapter pcf_epp_ops = { -+ .owner = THIS_MODULE, -+ .name = "PCF8584 EPP adapter", -+ .id = I2C_HW_P_LP, -+ .algo_data = &pcf_epp_data, -+}; -+ -+static int __init i2c_pcfepp_init(void) -+{ -+ struct i2c_pcf_epp *pepp = &gpe; -+ -+ printk(KERN_DEBUG "i2c-pcf-epp.o: i2c pcf8584-epp adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); -+ if (base == 0) -+ pepp->pe_base = DEFAULT_BASE; -+ else -+ pepp->pe_base = base; -+ -+ if (irq == 0) -+ pepp->pe_irq = DEFAULT_IRQ; -+ else if (irq<0) { -+ // switch off irq -+ pepp->pe_irq=0; -+ } else { -+ pepp->pe_irq = irq; -+ } -+ if (clock == 0) -+ pepp->pe_clock = DEFAULT_CLOCK; -+ else -+ pepp->pe_clock = clock; -+ -+ if (own == 0) -+ pepp->pe_own = DEFAULT_OWN; -+ else -+ pepp->pe_own = own; -+ -+ pcf_epp_data.data = (void *)pepp; -+ init_waitqueue_head(&pcf_wait); -+ if (pcf_epp_init(pepp) == 0) { -+ int ret; -+ if ( (ret = i2c_pcf_add_bus(&pcf_epp_ops)) < 0) { -+ printk(KERN_WARNING "i2c_pcf_add_bus caused an error: %d\n",ret); -+ release_region(pepp->pe_base , 5); -+ return ret; -+ } -+ } else { -+ -+ return -ENODEV; -+ } -+ printk(KERN_DEBUG "i2c-pcf-epp.o: found device at %#x.\n", pepp->pe_base); -+ return 0; -+} -+ -+static void __exit pcf_epp_exit(void) -+{ -+ i2c_pcf_del_bus(&pcf_epp_ops); -+ if (gpe.pe_irq > 0) { -+ disable_irq(gpe.pe_irq); -+ free_irq(gpe.pe_irq, 0); -+ } -+ release_region(gpe.pe_base , 5); -+} -+ -+MODULE_AUTHOR("Hans Berglund <hb@spacetec.no> \n modified by Ryosuke Tajima <rosk@jsk.t.u-tokyo.ac.jp>"); -+MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 EPP parallel port adapter"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(base, "i"); -+MODULE_PARM(irq, "i"); -+MODULE_PARM(clock, "i"); -+MODULE_PARM(own, "i"); -+MODULE_PARM(i2c_debug, "i"); -+ -+module_init(i2c_pcfepp_init); -+module_exit(pcf_epp_exit); ---- linux-old/include/linux/i2c-pcf8584.h Thu Jan 1 00:00:00 1970 -+++ linux/include/linux/i2c-pcf8584.h Mon Dec 13 19:26:34 2004 -@@ -0,0 +1,78 @@ -+/* -------------------------------------------------------------------- */ -+/* i2c-pcf8584.h: PCF 8584 global defines */ -+/* -------------------------------------------------------------------- */ -+/* Copyright (C) 1996 Simon G. Vogl -+ 1999 Hans Berglund -+ -+ 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 Frodo Looijaard <frodol@dds.nl> */ -+ -+/* $Id: i2c-pcf8584.h,v 1.6 2003/07/25 07:56:42 khali Exp $ */ -+ -+#ifndef _LINUX_I2C_PCF8584_H -+#define _LINUX_I2C_PCF8584_H -+ -+/* ----- Control register bits ---------------------------------------- */ -+#define I2C_PCF_PIN 0x80 -+#define I2C_PCF_ESO 0x40 -+#define I2C_PCF_ES1 0x20 -+#define I2C_PCF_ES2 0x10 -+#define I2C_PCF_ENI 0x08 -+#define I2C_PCF_STA 0x04 -+#define I2C_PCF_STO 0x02 -+#define I2C_PCF_ACK 0x01 -+ -+#define I2C_PCF_START (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK) -+#define I2C_PCF_STOP (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STO | I2C_PCF_ACK) -+#define I2C_PCF_REPSTART ( I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK) -+#define I2C_PCF_IDLE (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_ACK) -+ -+/* ----- Status register bits ----------------------------------------- */ -+/*#define I2C_PCF_PIN 0x80 as above*/ -+ -+#define I2C_PCF_INI 0x40 /* 1 if not initialized */ -+#define I2C_PCF_STS 0x20 -+#define I2C_PCF_BER 0x10 -+#define I2C_PCF_AD0 0x08 -+#define I2C_PCF_LRB 0x08 -+#define I2C_PCF_AAS 0x04 -+#define I2C_PCF_LAB 0x02 -+#define I2C_PCF_BB 0x01 -+ -+/* ----- Chip clock frequencies --------------------------------------- */ -+#define I2C_PCF_CLK3 0x00 -+#define I2C_PCF_CLK443 0x10 -+#define I2C_PCF_CLK6 0x14 -+#define I2C_PCF_CLK 0x18 -+#define I2C_PCF_CLK12 0x1c -+ -+/* ----- transmission frequencies ------------------------------------- */ -+#define I2C_PCF_TRNS90 0x00 /* 90 kHz */ -+#define I2C_PCF_TRNS45 0x01 /* 45 kHz */ -+#define I2C_PCF_TRNS11 0x02 /* 11 kHz */ -+#define I2C_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 I2C_PCF_OWNADR 0 -+#define I2C_PCF_INTREG I2C_PCF_ES2 -+#define I2C_PCF_CLKREG I2C_PCF_ES1 -+ -+#endif /* _LINUX_I2C_PCF8584_H */ ---- linux-old/drivers/i2c/i2c-philips-par.c Fri Feb 20 01:22:16 2004 -+++ linux/drivers/i2c/i2c-philips-par.c Mon Dec 13 19:26:34 2004 -@@ -21,7 +21,7 @@ - /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even - Frodo Looijaard <frodol@dds.nl> */ - --/* $Id: i2c-philips-par.c,v 1.18 2000/07/06 19:21:49 frodo Exp $ */ -+/* $Id: i2c-philips-par.c,v 1.33 2004/01/23 20:22:53 khali Exp $ */ - - #include <linux/kernel.h> - #include <linux/ioport.h> -@@ -29,14 +29,10 @@ - #include <linux/init.h> - #include <linux/stddef.h> - #include <linux/parport.h> -- -+#include <linux/slab.h> - #include <linux/i2c.h> - #include <linux/i2c-algo-bit.h> - --#ifndef __exit --#define __exit __init --#endif -- - static int type; - - struct i2c_par -@@ -130,59 +126,34 @@ - PARPORT_STATUS_BUSY) ? 0 : 1; - } - --static int bit_lp_reg(struct i2c_client *client) --{ -- return 0; --} -- --static int bit_lp_unreg(struct i2c_client *client) --{ -- return 0; --} -- --static void bit_lp_inc_use(struct i2c_adapter *adap) --{ -- MOD_INC_USE_COUNT; --} -- --static void bit_lp_dec_use(struct i2c_adapter *adap) --{ -- MOD_DEC_USE_COUNT; --} -- - /* ------------------------------------------------------------------------ - * 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_lp_data = { -- NULL, -- bit_lp_setsda, -- bit_lp_setscl, -- bit_lp_getsda, -- bit_lp_getscl, -- 80, 80, 100, /* waits, timeout */ -+ .setsda = bit_lp_setsda, -+ .setscl = bit_lp_setscl, -+ .getsda = bit_lp_getsda, -+ .getscl = bit_lp_getscl, -+ .udelay = 80, -+ .mdelay = 80, -+ .timeout = HZ - }; - - static struct i2c_algo_bit_data bit_lp_data2 = { -- NULL, -- bit_lp_setsda2, -- bit_lp_setscl2, -- bit_lp_getsda2, -- NULL, -- 80, 80, 100, /* waits, timeout */ -+ .setsda = bit_lp_setsda2, -+ .setscl = bit_lp_setscl2, -+ .getsda = bit_lp_getsda2, -+ .udelay = 80, -+ .mdelay = 80, -+ .timeout = HZ - }; - - static struct i2c_adapter bit_lp_ops = { -- "Philips Parallel port adapter", -- I2C_HW_B_LP, -- NULL, -- NULL, -- bit_lp_inc_use, -- bit_lp_dec_use, -- bit_lp_reg, -- -- bit_lp_unreg, -+ .owner = THIS_MODULE, -+ .name = "Philips Parallel port adapter", -+ .id = I2C_HW_B_LP, - }; - - static void i2c_parport_attach (struct parport *port) -@@ -202,6 +173,7 @@ - NULL); - if (!adapter->pdev) { - printk(KERN_ERR "i2c-philips-par: Unable to register with parport.\n"); -+ kfree(adapter); - return; - } - -@@ -210,8 +182,12 @@ - adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data; - adapter->bit_lp_data.data = port; - -+ if (parport_claim_or_block(adapter->pdev) < 0 ) { -+ printk(KERN_ERR "i2c-philips-par: Could not claim parallel port.\n"); -+ kfree(adapter); -+ return; -+ } - /* reset hardware to sane state */ -- parport_claim_or_block(adapter->pdev); - adapter->bit_lp_data.setsda(port, 1); - adapter->bit_lp_data.setscl(port, 1); - parport_release(adapter->pdev); -@@ -257,7 +233,7 @@ - NULL - }; - --int __init i2c_bitlp_init(void) -+static int __init i2c_bitlp_init(void) - { - printk(KERN_INFO "i2c-philips-par.o: i2c Philips parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - -@@ -266,7 +242,7 @@ - return 0; - } - --void __exit i2c_bitlp_exit(void) -+static void __exit i2c_bitlp_exit(void) - { - parport_unregister_driver(&i2c_driver); - } -@@ -279,14 +255,5 @@ - - MODULE_PARM(type, "i"); - --#ifdef MODULE --int init_module(void) --{ -- return i2c_bitlp_init(); --} -- --void cleanup_module(void) --{ -- i2c_bitlp_exit(); --} --#endif -+module_init(i2c_bitlp_init); -+module_exit(i2c_bitlp_exit); ---- linux-old/drivers/i2c/i2c-pport.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-pport.c Mon Dec 13 19:26:34 2004 -@@ -0,0 +1,169 @@ -+/* ------------------------------------------------------------------------- */ -+/* i2c-pport.c i2c-hw access for primitive i2c par. port adapter */ -+/* ------------------------------------------------------------------------- */ -+/* Copyright (C) 2001 Daniel Smolik -+ -+ 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. */ -+/* ------------------------------------------------------------------------- */ -+ -+/* -+ See doc/i2c-pport for instructions on wiring to the -+ parallel port connector. -+ -+ Cut & paste :-) based on Velleman K8000 driver by Simon G. Vogl -+ -+ Note that SDA is hardware inverted. -+*/ -+ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/ioport.h> -+#include <linux/errno.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-bit.h> -+#include <asm/io.h> -+ -+ -+#define DEFAULT_BASE 0x378 -+static int base = DEFAULT_BASE; -+static unsigned char PortData = 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 */ -+ -+/* we will use SDA - Auto Linefeed(14) POUT (ctrl bit 1) */ -+/* we will use SCL - Initialize printer(16) BUSY (ctrl bit 2) */ -+ -+#define SET_SCL | 0x04 -+#define CLR_SCL & 0xFB -+ -+#define SET_SDA & 0xFD -+#define CLR_SDA | 0x02 -+ -+ -+/* ----- local functions ---------------------------------------------- */ -+ -+ -+static void bit_pport_setscl(void *data, int state) -+{ -+ if (state) { -+ PortData = PortData SET_SCL; -+ } else { -+ PortData = PortData CLR_SCL; -+ } -+ outb(PortData, CTRL); -+} -+ -+static void bit_pport_setsda(void *data, int state) -+{ -+ if (state) { -+ PortData = PortData SET_SDA; -+ } else { -+ PortData = PortData CLR_SDA; -+ } -+ outb(PortData, CTRL); -+} -+ -+static int bit_pport_getscl(void *data) -+{ -+ return ( 4 == ( (inb_p(CTRL)) & 0x04 ) ); -+} -+ -+static int bit_pport_getsda(void *data) -+{ -+ return ( 0 == ( (inb_p(CTRL)) & 0x02 ) ); -+} -+ -+static int bit_pport_init(void) -+{ -+ if (!request_region((base+2),1, "i2c (PPORT adapter)")) { -+ return -ENODEV; -+ } -+ -+ PortData = inb(base+2); -+ bit_pport_setsda((void*)base, 1); -+ bit_pport_setscl((void*)base, 1); -+ -+ return 0; -+} -+ -+ -+/* ------------------------------------------------------------------------ -+ * 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_pport_data = { -+ .setsda = bit_pport_setsda, -+ .setscl = bit_pport_setscl, -+ .getsda = bit_pport_getsda, -+ .getscl = bit_pport_getscl, -+ .udelay = 40, -+ .mdelay = 80, -+ .timeout = HZ -+}; -+ -+static struct i2c_adapter bit_pport_ops = { -+ .owner = THIS_MODULE, -+ .name = "Primitive Parallel port adaptor", -+ .id = I2C_HW_B_PPORT, -+ .algo_data = &bit_pport_data, -+}; -+ -+static int __init i2c_bitpport_init(void) -+{ -+ printk("i2c-pport.o: i2c Primitive parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); -+ -+ bit_pport_data.data = (void*)base; -+ if (bit_pport_init() < 0) -+ return -ENODEV; -+ -+ if (i2c_bit_add_bus(&bit_pport_ops) < 0) { -+ release_region(base+2, 1); -+ return -ENODEV; -+ } -+ -+ printk("i2c-pport.o: found device at %#x.\n",base); -+ return 0; -+} -+ -+static void __exit i2c_bitpport_exit(void) -+{ -+ i2c_bit_del_bus(&bit_pport_ops); -+ release_region((base+2),1); -+} -+ -+EXPORT_NO_SYMBOLS; -+ -+MODULE_AUTHOR("Daniel Smolik <marvin@sitour.cz>"); -+MODULE_DESCRIPTION("I2C-Bus adapter routines for Primitive parallel port adapter"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(base, "i"); -+ -+module_init(i2c_bitpport_init); -+module_exit(i2c_bitpport_exit); ---- linux-old/drivers/i2c/i2c-proc.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-proc.c Mon Dec 13 19:26:35 2004 -@@ -23,29 +23,26 @@ - This driver puts entries in /proc/sys/dev/sensors for each I2C device - */ - -+#include <linux/config.h> - #include <linux/module.h> - #include <linux/kernel.h> - #include <linux/slab.h> - #include <linux/ctype.h> - #include <linux/sysctl.h> - #include <linux/proc_fs.h> -+#include <linux/init.h> - #include <linux/ioport.h> --#include <asm/uaccess.h> -- - #include <linux/i2c.h> - #include <linux/i2c-proc.h> -+#include <asm/uaccess.h> - --#include <linux/init.h> -- --#ifndef THIS_MODULE --#define THIS_MODULE NULL -+#ifndef CONFIG_SYSCTL -+#error Your kernel lacks sysctl support (CONFIG_SYSCTL)! - #endif - --static int i2c_create_name(char **name, const char *prefix, -- struct i2c_adapter *adapter, int addr); - static int i2c_parse_reals(int *nrels, void *buffer, int bufsize, - long *results, int magnitude); --static int i2c_write_reals(int nrels, void *buffer, int *bufsize, -+static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize, - long *results, int magnitude); - static int i2c_proc_chips(ctl_table * ctl, int write, - struct file *filp, void *buffer, -@@ -55,22 +52,10 @@ - void *newval, size_t newlen, - void **context); - --int __init sensors_init(void); -- - #define SENSORS_ENTRY_MAX 20 - static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX]; - - static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX]; --static unsigned short i2c_inodes[SENSORS_ENTRY_MAX]; -- --static ctl_table sysctl_table[] = { -- {CTL_DEV, "dev", NULL, 0, 0555}, -- {0}, -- {DEV_SENSORS, "sensors", NULL, 0, 0555}, -- {0}, -- {0, NULL, NULL, 0, 0555}, -- {0} --}; - - static ctl_table i2c_proc_dev_sensors[] = { - {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips, -@@ -91,31 +76,45 @@ - - - static struct ctl_table_header *i2c_proc_header; --static int i2c_initialized; - - /* This returns a nice name for a new directory; for example lm78-isa-0310 - (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for - a LM75 chip on the third i2c bus at address 0x4e). - name is allocated first. */ --int i2c_create_name(char **name, const char *prefix, -- struct i2c_adapter *adapter, int addr) -+static char *generate_name(struct i2c_client *client, const char *prefix) - { -- char name_buffer[50]; -- int id; -- if (i2c_is_isa_adapter(adapter)) -+ struct i2c_adapter *adapter = client->adapter; -+ int addr = client->addr; -+ char name_buffer[50], *name; -+ -+ if (i2c_is_isa_adapter(adapter)) { - sprintf(name_buffer, "%s-isa-%04x", prefix, addr); -- else { -- if ((id = i2c_adapter_id(adapter)) < 0) -- return -ENOENT; -+ } else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) { -+ int id = i2c_adapter_id(adapter); -+ if (id < 0) -+ return ERR_PTR(-ENOENT); - sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr); -+ } else { /* dummy adapter, generate prefix */ -+ int end, i; -+ -+ sprintf(name_buffer, "%s-", prefix); -+ end = strlen(name_buffer); -+ -+ for (i = 0; i < 32; i++) { -+ if (adapter->algo->name[i] == ' ') -+ break; -+ name_buffer[end++] = tolower(adapter->algo->name[i]); -+ } -+ -+ name_buffer[end] = 0; -+ sprintf(name_buffer + end, "-%04x", addr); - } -- *name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL); -- if (!*name) { -- printk (KERN_WARNING "i2c_create_name: not enough memory\n"); -- return -ENOMEM; -- } -- strcpy(*name, name_buffer); -- return 0; -+ -+ name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL); -+ if (!name) -+ return ERR_PTR(-ENOMEM); -+ strcpy(name, name_buffer); -+ return name; - } - - /* This rather complex function must be called when you want to add an entry -@@ -124,139 +123,91 @@ - ctl_template should be a template of the newly created directory. It is - copied in memory. The extra2 field of each file is set to point to client. - If any driver wants subdirectories within the newly created directory, -- this function must be updated! -- controlling_mod is the controlling module. It should usually be -- THIS_MODULE when calling. Note that this symbol is not defined in -- kernels before 2.3.13; define it to NULL in that case. We will not use it -- for anything older than 2.3.27 anyway. */ -+ this function must be updated! */ - int i2c_register_entry(struct i2c_client *client, const char *prefix, -- ctl_table * ctl_template, -- struct module *controlling_mod) -+ struct ctl_table *ctl_template) - { -- int i, res, len, id; -- ctl_table *new_table; -- char *name; -- struct ctl_table_header *new_header; -- -- if ((res = i2c_create_name(&name, prefix, client->adapter, -- client->addr))) return res; -+ struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl; -+ struct ctl_table_header *hdr; -+ struct ctl_table *tmp, *leaf; -+ const char *name; -+ int id, len = 0; - -- for (id = 0; id < SENSORS_ENTRY_MAX; id++) -- if (!i2c_entries[id]) { -- break; -- } -- if (id == SENSORS_ENTRY_MAX) { -- kfree(name); -- return -ENOMEM; -- } -- id += 256; -+ name = generate_name(client, prefix); -+ if (IS_ERR(name)) -+ return PTR_ERR(name); - -- len = 0; -- while (ctl_template[len].procname) -- len++; -- len += 7; -- if (!(new_table = kmalloc(sizeof(ctl_table) * len, GFP_KERNEL))) { -- kfree(name); -- return -ENOMEM; -- } -- -- memcpy(new_table, sysctl_table, 6 * sizeof(ctl_table)); -- new_table[0].child = &new_table[2]; -- new_table[2].child = &new_table[4]; -- new_table[4].child = &new_table[6]; -- new_table[4].procname = name; -- new_table[4].ctl_name = id; -- memcpy(new_table + 6, ctl_template, (len - 6) * sizeof(ctl_table)); -- for (i = 6; i < len; i++) -- new_table[i].extra2 = client; -- -- if (!(new_header = register_sysctl_table(new_table, 0))) { -- kfree(new_table); -- kfree(name); -- return -ENOMEM; -+ for (id = 0; id < SENSORS_ENTRY_MAX; id++) { -+ if (!i2c_entries[id]) -+ goto free_slot; - } - -- i2c_entries[id - 256] = new_header; -+ goto out_free_name; - -- i2c_clients[id - 256] = client; --#ifdef DEBUG -- if (!new_header || !new_header->ctl_table || -- !new_header->ctl_table->child || -- !new_header->ctl_table->child->child || -- !new_header->ctl_table->child->child->de) { -- printk -- ("i2c-proc.o: NULL pointer when trying to install fill_inode fix!\n"); -- return id; -- } --#endif /* DEBUG */ -- i2c_inodes[id - 256] = -- new_header->ctl_table->child->child->de->low_ino; -- new_header->ctl_table->child->child->de->owner = controlling_mod; -- -- return id; -+ free_slot: -+ while (ctl_template[len].ctl_name) -+ len++; -+ tbl = kmalloc(sizeof(*tbl) + sizeof(ctl_table) * (len + 1), -+ GFP_KERNEL); -+ if (!tbl) -+ goto out_free_name; -+ memset(tbl, 0, sizeof(*tbl)); -+ -+ /* The client sysctls */ -+ leaf = (struct ctl_table *) (tbl + 1); -+ memcpy(leaf, ctl_template, sizeof(ctl_table) * (len+1)); -+ for (tmp = leaf; tmp->ctl_name; tmp++) -+ tmp->extra2 = client; -+ -+ tbl->sensors->ctl_name = id+256; -+ tbl->sensors->procname = name; -+ tbl->sensors->mode = 0555; -+ tbl->sensors->child = leaf; -+ -+ tbl->dev->ctl_name = DEV_SENSORS; -+ tbl->dev->procname = "sensors"; -+ tbl->dev->mode = 0555; -+ tbl->dev->child = tbl->sensors; -+ -+ tbl->root->ctl_name = CTL_DEV; -+ tbl->root->procname = "dev"; -+ tbl->root->mode = 0555; -+ tbl->root->child = tbl->dev; -+ -+ hdr = register_sysctl_table(tbl->root, 0); -+ if (!hdr) -+ goto out_free_tbl; -+ -+ i2c_entries[id] = hdr; -+ i2c_clients[id] = client; -+ -+ return (id + 256); /* XXX(hch) why?? */ -+ -+ out_free_tbl: -+ kfree(tbl); -+ out_free_name: -+ kfree(name); -+ return -ENOMEM; - } - - void i2c_deregister_entry(int id) - { -- ctl_table *table; -- char *temp; - id -= 256; -- if (i2c_entries[id]) { -- table = i2c_entries[id]->ctl_table; -- unregister_sysctl_table(i2c_entries[id]); -- /* 2-step kfree needed to keep gcc happy about const points */ -- (const char *) temp = table[4].procname; -- kfree(temp); -- kfree(table); -- i2c_entries[id] = NULL; -- i2c_clients[id] = NULL; -- } --} - --/* Monitor access for /proc/sys/dev/sensors; make unloading i2c-proc.o -- impossible if some process still uses it or some file in it */ --void i2c_fill_inode(struct inode *inode, int fill) --{ -- if (fill) -- MOD_INC_USE_COUNT; -- else -- MOD_DEC_USE_COUNT; --} -- --/* Monitor access for /proc/sys/dev/sensors/ directories; make unloading -- the corresponding module impossible if some process still uses it or -- some file in it */ --void i2c_dir_fill_inode(struct inode *inode, int fill) --{ -- int i; -- struct i2c_client *client; -+ if (i2c_entries[id]) { -+ struct ctl_table_header *hdr = i2c_entries[id]; -+ struct ctl_table *tbl = hdr->ctl_table; - --#ifdef DEBUG -- if (!inode) { -- printk("i2c-proc.o: Warning: inode NULL in fill_inode()\n"); -- return; -+ unregister_sysctl_table(hdr); -+ kfree(tbl->child->child->procname); -+ kfree(tbl); /* actually the whole anonymous struct */ - } --#endif /* def DEBUG */ - -- for (i = 0; i < SENSORS_ENTRY_MAX; i++) -- if (i2c_clients[i] -- && (i2c_inodes[i] == inode->i_ino)) break; --#ifdef DEBUG -- if (i == SENSORS_ENTRY_MAX) { -- printk -- ("i2c-proc.o: Warning: inode (%ld) not found in fill_inode()\n", -- inode->i_ino); -- return; -- } --#endif /* def DEBUG */ -- client = i2c_clients[i]; -- if (fill) -- client->driver->inc_use(client); -- else -- client->driver->dec_use(client); -+ i2c_entries[id] = NULL; -+ i2c_clients[id] = NULL; - } - --int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp, -+static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp, - void *buffer, size_t * lenp) - { - char BUF[SENSORS_PREFIX_MAX + 30]; -@@ -294,7 +245,7 @@ - return 0; - } - --int i2c_sysctl_chips(ctl_table * table, int *name, int nlen, -+static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen, - void *oldval, size_t * oldlenp, void *newval, - size_t newlen, void **context) - { -@@ -456,7 +407,7 @@ - WARNING! This is tricky code. I have tested it, but there may still be - hidden bugs in it, even leading to crashes and things! - */ --int i2c_parse_reals(int *nrels, void *buffer, int bufsize, -+static int i2c_parse_reals(int *nrels, void *buffer, int bufsize, - long *results, int magnitude) - { - int maxels, min, mag; -@@ -557,7 +508,7 @@ - return 0; - } - --int i2c_write_reals(int nrels, void *buffer, int *bufsize, -+static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize, - long *results, int magnitude) - { - #define BUFLEN 20 -@@ -646,6 +597,7 @@ - I2C_FUNC_SMBUS_QUICK)) return -1; - - for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) { -+ /* XXX: WTF is going on here??? */ - if ((is_isa && check_region(addr, 1)) || - (!is_isa && i2c_check_addr(adapter, addr))) - continue; -@@ -846,46 +798,33 @@ - return 0; - } - --int __init sensors_init(void) -+static int __init i2c_proc_init(void) - { - printk(KERN_INFO "i2c-proc.o version %s (%s)\n", I2C_VERSION, I2C_DATE); -- i2c_initialized = 0; - if (! - (i2c_proc_header = -- register_sysctl_table(i2c_proc, 0))) return -ENOMEM; -+ register_sysctl_table(i2c_proc, 0))) { -+ printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n"); -+ return -EPERM; -+ } - i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE; -- i2c_initialized++; - return 0; - } - -+static void __exit i2c_proc_exit(void) -+{ -+ unregister_sysctl_table(i2c_proc_header); -+} -+ -+EXPORT_SYMBOL(i2c_register_entry); - EXPORT_SYMBOL(i2c_deregister_entry); --EXPORT_SYMBOL(i2c_detect); - EXPORT_SYMBOL(i2c_proc_real); --EXPORT_SYMBOL(i2c_register_entry); - EXPORT_SYMBOL(i2c_sysctl_real); -- --#ifdef MODULE -+EXPORT_SYMBOL(i2c_detect); - - MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); - MODULE_DESCRIPTION("i2c-proc driver"); - MODULE_LICENSE("GPL"); - --int i2c_cleanup(void) --{ -- if (i2c_initialized >= 1) { -- unregister_sysctl_table(i2c_proc_header); -- i2c_initialized--; -- } -- return 0; --} -- --int init_module(void) --{ -- return sensors_init(); --} -- --int cleanup_module(void) --{ -- return i2c_cleanup(); --} --#endif /* MODULE */ -+module_init(i2c_proc_init); -+module_exit(i2c_proc_exit); ---- linux-old/include/linux/i2c-proc.h Tue Nov 6 00:55:29 2001 -+++ linux/include/linux/i2c-proc.h Mon Dec 13 19:26:36 2004 -@@ -1,6 +1,7 @@ - /* -- sensors.h - Part of lm_sensors, Linux kernel modules for hardware -- monitoring -+ i2c-proc.h - Part of the i2c package -+ was originally sensors.h - Part of lm_sensors, Linux kernel modules -+ for hardware monitoring - Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> - - This program is free software; you can redistribute it and/or modify -@@ -18,14 +19,9 @@ - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - --#ifndef SENSORS_SENSORS_H --#define SENSORS_SENSORS_H -+#ifndef _LINUX_I2C_PROC_H -+#define _LINUX_I2C_PROC_H - --#ifdef __KERNEL__ -- --/* Next two must be included before sysctl.h can be included, in 2.0 kernels */ --#include <linux/types.h> --#include <linux/fs.h> - #include <linux/sysctl.h> - - /* The type of callback functions used in sensors_{proc,sysctl}_real */ -@@ -73,8 +69,7 @@ - these functions must be updated! */ - extern int i2c_register_entry(struct i2c_client *client, - const char *prefix, -- ctl_table * ctl_template, -- struct module *controlling_mod); -+ ctl_table * ctl_template); - - extern void i2c_deregister_entry(int id); - -@@ -347,6 +342,31 @@ - {NULL}}; \ - SENSORS_INSMOD - -+#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \ -+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \ -+ SENSORS_MODULE_PARM(force, \ -+ "List of adapter,address pairs to boldly assume " \ -+ "to be present"); \ -+ SENSORS_MODULE_PARM_FORCE(chip1); \ -+ SENSORS_MODULE_PARM_FORCE(chip2); \ -+ SENSORS_MODULE_PARM_FORCE(chip3); \ -+ SENSORS_MODULE_PARM_FORCE(chip4); \ -+ SENSORS_MODULE_PARM_FORCE(chip5); \ -+ SENSORS_MODULE_PARM_FORCE(chip6); \ -+ SENSORS_MODULE_PARM_FORCE(chip7); \ -+ SENSORS_MODULE_PARM_FORCE(chip8); \ -+ static struct i2c_force_data forces[] = {{force,any_chip}, \ -+ {force_ ## chip1,chip1}, \ -+ {force_ ## chip2,chip2}, \ -+ {force_ ## chip3,chip3}, \ -+ {force_ ## chip4,chip4}, \ -+ {force_ ## chip5,chip5}, \ -+ {force_ ## chip6,chip6}, \ -+ {force_ ## chip7,chip7}, \ -+ {force_ ## chip8,chip8}, \ -+ {NULL}}; \ -+ SENSORS_INSMOD -+ - typedef int i2c_found_addr_proc(struct i2c_adapter *adapter, - int addr, unsigned short flags, - int kind); -@@ -362,7 +382,7 @@ - - /* This macro is used to scale user-input to sensible values in almost all - chip drivers. */ --extern inline int SENSORS_LIMIT(long value, long low, long high) -+static inline int SENSORS_LIMIT(long value, long low, long high) - { - if (value < low) - return low; -@@ -372,8 +392,6 @@ - return value; - } - --#endif /* def __KERNEL__ */ -- - - /* The maximum length of the prefix */ - #define SENSORS_PREFIX_MAX 20 -@@ -392,5 +410,5 @@ - char name[SENSORS_PREFIX_MAX + 13]; - }; - --#endif /* def SENSORS_SENSORS_H */ -+#endif /* def _LINUX_I2C_PROC_H */ - ---- linux-old/drivers/i2c/i2c-rpx.c Thu Jan 1 00:00:00 1970 -+++ linux/drivers/i2c/i2c-rpx.c Mon Dec 13 19:26:36 2004 -@@ -0,0 +1,101 @@ -+/* -+ * Embedded Planet RPX Lite MPC8xx CPM I2C interface. -+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). -+ * -+ * moved into proper i2c interface; -+ * Brad Parker (brad@heeltoe.com) -+ * -+ * RPX lite specific parts of the i2c interface -+ * Update: There actually isn't anything RPXLite-specific about this module. -+ * This should work for most any 8xx board. The console messages have been -+ * changed to eliminate RPXLite references. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/stddef.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-8xx.h> -+#include <asm/mpc8xx.h> -+#include <asm/commproc.h> -+ -+ -+static void -+rpx_iic_init(struct i2c_algo_8xx_data *data) -+{ -+ volatile cpm8xx_t *cp; -+ volatile immap_t *immap; -+ -+ cp = cpmp; /* Get pointer to Communication Processor */ -+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ -+ -+ data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; -+ -+ /* Check for and use a microcode relocation patch. -+ */ -+ if ((data->reloc = data->iip->iic_rpbase)) -+ data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase]; -+ -+ data->i2c = (i2c8xx_t *)&(immap->im_i2c); -+ data->cp = cp; -+ -+ /* Initialize Port B IIC pins. -+ */ -+ cp->cp_pbpar |= 0x00000030; -+ cp->cp_pbdir |= 0x00000030; -+ cp->cp_pbodr |= 0x00000030; -+ -+ /* Allocate space for two transmit and two receive buffer -+ * descriptors in the DP ram. -+ */ -+ data->dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 4); -+ -+ /* ptr to i2c area */ -+ data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c); -+} -+ -+static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data) -+{ -+ /* install interrupt handler */ -+ cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data); -+ -+ return 0; -+} -+ -+static struct i2c_algo_8xx_data rpx_data = { -+ .setisr = rpx_install_isr -+}; -+ -+static struct i2c_adapter rpx_ops = { -+ .owner = THIS_MODULE, -+ .name = "m8xx", -+ .id = I2C_HW_MPC8XX_EPON, -+ .algo_data = &rpx_data, -+}; -+ -+static int __init i2c_rpx_init(void) -+{ -+ printk("i2c-rpx.o: i2c MPC8xx module version %s (%s)\n", I2C_VERSION, I2C_DATE); -+ -+ /* reset hardware to sane state */ -+ rpx_iic_init(&rpx_data); -+ -+ if (i2c_8xx_add_bus(&rpx_ops) < 0) { -+ printk("i2c-rpx: Unable to register with I2C\n"); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit i2c_rpx_exit(void) -+{ -+ i2c_8xx_del_bus(&rpx_ops); -+} -+ -+MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>"); -+MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards"); -+ -+module_init(i2c_rpx_init); -+module_exit(i2c_rpx_exit); ---- linux-old/drivers/i2c/i2c-velleman.c Tue Jan 20 15:10:31 2004 -+++ linux/drivers/i2c/i2c-velleman.c Mon Dec 13 19:26:36 2004 -@@ -18,18 +18,18 @@ - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* ------------------------------------------------------------------------- */ - --/* $Id: i2c-velleman.c,v 1.19 2000/01/24 02:06:33 mds Exp $ */ -+/* $Id: i2c-velleman.c,v 1.33 2003/12/24 17:49:44 khali Exp $ */ - - #include <linux/kernel.h> - #include <linux/ioport.h> - #include <linux/module.h> - #include <linux/init.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 <linux/errno.h> -+#include <linux/delay.h> - #include <linux/i2c.h> - #include <linux/i2c-algo-bit.h> -+#include <asm/io.h> -+#include <asm/param.h> /* for HZ */ - - /* ----- global defines ----------------------------------------------- */ - #define DEB(x) /* should be reasonable open, close &c. */ -@@ -90,75 +90,38 @@ - - static int bit_velle_init(void) - { -- if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) { -- DEBE(printk("i2c-velleman.o: Port %#x already in use.\n", -- base)); -+ if (!request_region(base, (base == 0x3bc) ? 3 : 8, -+ "i2c (Vellemann adapter)")) - 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; --} - --static void __exit bit_velle_exit(void) --{ -- release_region( base , (base == 0x3bc)? 3 : 8 ); --} -- -- --static int bit_velle_reg(struct i2c_client *client) --{ -- return 0; --} -- --static int bit_velle_unreg(struct i2c_client *client) --{ -+ bit_velle_setsda((void*)base,1); -+ bit_velle_setscl((void*)base,1); - return 0; - } - --static void bit_velle_inc_use(struct i2c_adapter *adap) --{ --#ifdef MODULE -- MOD_INC_USE_COUNT; --#endif --} -- --static void bit_velle_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_velle_data = { -- NULL, -- bit_velle_setsda, -- bit_velle_setscl, -- bit_velle_getsda, -- bit_velle_getscl, -- 10, 10, 100, /* waits, timeout */ -+ .setsda = bit_velle_setsda, -+ .setscl = bit_velle_setscl, -+ .getsda = bit_velle_getsda, -+ .getscl = bit_velle_getscl, -+ .udelay = 10, -+ .mdelay = 10, -+ .timeout = HZ - }; - - static struct i2c_adapter bit_velle_ops = { -- "Velleman K8000", -- I2C_HW_B_VELLE, -- NULL, -- &bit_velle_data, -- bit_velle_inc_use, -- bit_velle_dec_use, -- bit_velle_reg, -- bit_velle_unreg, -+ .owner = THIS_MODULE, -+ .name = "Velleman K8000", -+ .id = I2C_HW_B_VELLE, -+ .algo_data = &bit_velle_data, - }; - --int __init i2c_bitvelle_init(void) -+static int __init i2c_bitvelle_init(void) - { - printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - if (base==0) { -@@ -184,24 +147,19 @@ - return 0; - } - -+static void __exit i2c_bitvelle_exit(void) -+{ -+ i2c_bit_del_bus(&bit_velle_ops); -+ release_region(base, (base == 0x3bc) ? 3 : 8); -+} -+ - EXPORT_NO_SYMBOLS; - --#ifdef MODULE - MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); - MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter"); - MODULE_LICENSE("GPL"); - - MODULE_PARM(base, "i"); - --int init_module(void) --{ -- return i2c_bitvelle_init(); --} -- --void cleanup_module(void) --{ -- i2c_bit_del_bus(&bit_velle_ops); -- bit_velle_exit(); --} -- --#endif -+module_init(i2c_bitvelle_init); -+module_exit(i2c_bitvelle_exit); ---- linux-old/include/linux/i2c.h Tue Jan 20 15:10:34 2004 -+++ linux/include/linux/i2c.h Mon Dec 13 19:26:37 2004 -@@ -23,36 +23,33 @@ - /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and - Frodo Looijaard <frodol@dds.nl> */ - --/* $Id: i2c.h,v 1.46 2001/08/31 00:04:07 phil Exp $ */ -+/* $Id: i2c.h,v 1.80 2004/10/07 23:47:17 phil Exp $ */ - --#ifndef I2C_H --#define I2C_H -+#ifndef _LINUX_I2C_H -+#define _LINUX_I2C_H - --#define I2C_DATE "20010830" --#define I2C_VERSION "2.6.1" -+#define I2C_DATE "20041007" -+#define I2C_VERSION "2.8.8" - --#include <linux/i2c-id.h> /* id values of adapters et. al. */ -+#include <linux/module.h> - #include <linux/types.h> -- -- --struct i2c_msg; -- -- --#ifdef __KERNEL__ -- --/* --- Includes and compatibility declarations ------------------------ */ -- -+#include <linux/errno.h> -+#include <linux/sched.h> - #include <asm/semaphore.h> --#include <linux/config.h> -+#include <linux/i2c-id.h> -+ -+#include <linux/version.h> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -+#define MODULE_LICENSE(x) -+#endif - - /* --- General options ------------------------------------------------ */ - --#define I2C_ALGO_MAX 4 /* control memory consumption */ --#define I2C_ADAP_MAX 16 -+#define I2C_ADAP_MAX 16 /* control memory consumption */ - #define I2C_DRIVER_MAX 16 - #define I2C_CLIENT_MAX 32 --#define I2C_DUMMY_MAX 4 - -+struct i2c_msg; - struct i2c_algorithm; - struct i2c_adapter; - struct i2c_client; -@@ -60,7 +57,6 @@ - struct i2c_client_address_data; - union i2c_smbus_data; - -- - /* - * 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 -@@ -113,6 +109,8 @@ - extern s32 i2c_smbus_write_block_data(struct i2c_client * client, - u8 command, u8 length, - u8 *values); -+extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, -+ u8 command, u8 *values); - extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, - u8 command, u8 length, - u8 *values); -@@ -125,6 +123,7 @@ - */ - - struct i2c_driver { -+ struct module *owner; - char name[32]; - int id; - unsigned int flags; /* div., see below */ -@@ -148,18 +147,6 @@ - * 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. -- * You should use the i2c_{inc,dec}_use_client functions instead of -- * calling this function directly. -- */ -- void (*inc_use)(struct i2c_client *client); -- void (*dec_use)(struct i2c_client *client); - }; - - /* -@@ -192,6 +179,7 @@ - * to name two of the most common. - */ - struct i2c_algorithm { -+ struct module *owner; /* future use --km */ - char name[32]; /* textual description */ - unsigned int id; - -@@ -221,16 +209,13 @@ - * with the access algorithms necessary to access it. - */ - struct i2c_adapter { -+ struct module *owner; - 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 *algo_data; - -- /* --- These may be NULL, but should increase the module use count */ -- void (*inc_use)(struct i2c_adapter *); -- void (*dec_use)(struct i2c_adapter *); -- - /* --- administration stuff. */ - int (*client_register)(struct i2c_client *); - int (*client_unregister)(struct i2c_client *); -@@ -241,11 +226,11 @@ - /* and can be set via the i2c_ioctl call */ - - /* data fields that are valid for all devices */ -- struct semaphore lock; -+ struct semaphore bus; -+ struct semaphore list; - unsigned int flags;/* flags specifying div. data */ - - struct i2c_client *clients[I2C_CLIENT_MAX]; -- int client_count; - - int timeout; - int retries; -@@ -264,6 +249,9 @@ - #define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */ - #define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */ - /* on an i2c_client */ -+#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ -+#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */ -+ /* Must equal I2C_M_TEN below */ - - /* i2c_client_address_data is the struct for holding default client - * addresses for a driver and for the parameters supplied on the -@@ -302,12 +290,6 @@ - extern int i2c_attach_client(struct i2c_client *); - extern int i2c_detach_client(struct i2c_client *); - --/* Only call these if you grab a resource that makes unloading the -- client and the adapter it is on completely impossible. Like when a -- /proc directory is entered. */ --extern void i2c_inc_use_client(struct i2c_client *); --extern void i2c_dec_use_client(struct i2c_client *); -- - /* New function: This is to get an i2c_client-struct for controlling the - client either by using i2c_control-function or having the - client-module export functions that can be used with the i2c_client -@@ -341,6 +323,15 @@ - struct i2c_client_address_data *address_data, - i2c_client_found_addr_proc *found_proc); - -+static inline int i2c_client_command(struct i2c_client *client, -+ unsigned int cmd, void *arg) -+{ -+ if (client->driver && client->driver->command) -+ return client->driver->command(client, cmd, arg); -+ else -+ return -EINVAL; -+} -+ - /* An ioctl like call to set div. parameters of the adapter. - */ - extern int i2c_control(struct i2c_client *,unsigned int, unsigned long); -@@ -358,8 +349,6 @@ - /* Return 1 if adapter supports everything we need, 0 if not. */ - extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func); - --#endif /* __KERNEL__ */ -- - /* - * I2C Message - used for pure i2c transaction, also from /dev interface - */ -@@ -370,15 +359,28 @@ - #define I2C_M_RD 0x01 - #define I2C_M_NOSTART 0x4000 - #define I2C_M_REV_DIR_ADDR 0x2000 -+#define I2C_M_IGNORE_NAK 0x1000 -+#define I2C_M_NO_RD_ACK 0x0800 -+#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ -+#define I2C_M_RECV_PEC 0x0200 /* receive one more than the returned -+ length byte for the PEC */ - __u16 len; /* msg length */ - __u8 *buf; /* pointer to msg data */ -+ int err; -+ short done; - }; - - /* To determine what functionality is present */ - - #define I2C_FUNC_I2C 0x00000001 - #define I2C_FUNC_10BIT_ADDR 0x00000002 --#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART} */ -+#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ -+#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */ -+#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */ -+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ -+#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */ -+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */ -+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ - #define I2C_FUNC_SMBUS_QUICK 0x00010000 - #define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 - #define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 -@@ -389,8 +391,12 @@ - #define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 - #define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 - #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 --#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* New I2C-like block */ --#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* transfer */ -+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ -+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ -+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ -+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ -+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */ -+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */ - - #define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ - I2C_FUNC_SMBUS_WRITE_BYTE -@@ -402,13 +408,28 @@ - I2C_FUNC_SMBUS_WRITE_BLOCK_DATA - #define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK -+#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \ -+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 -+#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \ -+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC -+#define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \ -+ I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC -+ -+#define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA -+#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA -+#define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA -+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA -+#define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA -+#define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA - - #define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ - I2C_FUNC_SMBUS_BYTE | \ - I2C_FUNC_SMBUS_BYTE_DATA | \ - I2C_FUNC_SMBUS_WORD_DATA | \ - I2C_FUNC_SMBUS_PROC_CALL | \ -- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA -+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ -+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ -+ I2C_FUNC_SMBUS_I2C_BLOCK - - /* - * Data for SMBus Messages -@@ -418,8 +439,9 @@ - union i2c_smbus_data { - __u8 byte; - __u16 word; -- __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ -+ __u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */ - /* one more for read length in block process call */ -+ /* and one more for PEC */ - }; - - /* smbus_access read or write markers */ -@@ -435,6 +457,11 @@ - #define I2C_SMBUS_PROC_CALL 4 - #define I2C_SMBUS_BLOCK_DATA 5 - #define I2C_SMBUS_I2C_BLOCK_DATA 6 -+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ -+#define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */ -+#define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */ -+#define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */ -+#define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */ - - - /* ----- commands for the ioctl like i2c_command call: -@@ -460,6 +487,7 @@ - - #define I2C_FUNCS 0x0705 /* Get the adapter functionality */ - #define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/ -+#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */ - #if 0 - #define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */ - #endif -@@ -475,16 +503,6 @@ - - #define I2C_MAJOR 89 /* Device major number */ - --#ifdef __KERNEL__ -- --# ifndef NULL --# define NULL ( (void *) 0 ) --# endif -- --# ifndef ENODEV --# include <asm/errno.h> --# endif -- - /* These defines are used for probing i2c client addresses */ - /* Default fill of many variables */ - #define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ -@@ -546,5 +564,11 @@ - #define i2c_is_isa_adapter(adapptr) \ - ((adapptr)->algo->id == I2C_ALGO_ISA) - --#endif /* def __KERNEL__ */ --#endif /* I2C_H */ -+/* Tiny delay function used by the i2c bus drivers */ -+static inline void i2c_delay(signed long timeout) -+{ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(timeout); -+} -+ -+#endif /* _LINUX_I2C_H */ |