Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6: (30 commits)
  i2c: Drop unimplemented slave functions
  i2c: Constify i2c_algorithm declarations, part 2
  i2c: Constify i2c_algorithm declarations, part 1
  i2c: Let drivers constify i2c_algorithm data
  i2c-isa: Restore driver owner
  i2c-viapro: Add support for the VT8237A and VT8251
  i2c: Warn on i2c client creation failure
  i2c-core: Drop useless bitmaskings
  i2c-algo-pcf: Discard the mdelay data struct member
  i2c-algo-bit: Cleanups
  i2c-isa: Fail adding driver on attach_adapter error
  i2c: __must_check fixes (chip drivers)
  i2c-dev: attach/detach_adapter cleanups
  i2c-stub: Chip address as a module parameter
  i2c: Plan i2c-isa for removal
  i2c: New bus driver for TI OMAP boards
  i2c-algo-bit: Discard the mdelay data struct member
  i2c-matroxfb: Struct init conversion
  i2c: Fix copy-n-paste in subsystem Kconfig
  i2c-au1550: Add I2C support for Au1200
  ...
This commit is contained in:
Linus Torvalds 2006-09-27 08:09:48 -07:00
commit a5b08073a0
83 changed files with 1221 additions and 484 deletions

View File

@ -313,3 +313,12 @@ Why: The stacking of class devices makes these values misleading and
Who: Kay Sievers <kay.sievers@suse.de>
---------------------------
What: i2c-isa
When: December 2006
Why: i2c-isa is a non-sense and doesn't fit in the device driver
model. Drivers relying on it are better implemented as platform
drivers.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------

View File

@ -7,9 +7,12 @@ Supported adapters:
* VIA Technologies, Inc. VT82C686A/B
Datasheet: Sometimes available at the VIA website
* VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237R
* VIA Technologies, Inc. VT8231, VT8233, VT8233A
Datasheet: available on request from VIA
* VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251
Datasheet: available on request and under NDA from VIA
Authors:
Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>,
@ -39,6 +42,8 @@ Your lspci -n listing must show one of these :
device 1106:8235 (VT8231 function 4)
device 1106:3177 (VT8235)
device 1106:3227 (VT8237R)
device 1106:3337 (VT8237A)
device 1106:3287 (VT8251)
If none of these show up, you should look in the BIOS for settings like
enable ACPI / SMBus or even USB.

View File

@ -6,9 +6,12 @@ This module is a very simple fake I2C/SMBus driver. It implements four
types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, and
(r/w) word data.
You need to provide a chip address as a module parameter when loading
this driver, which will then only react to SMBus commands to this address.
No hardware is needed nor associated with this module. It will accept write
quick commands to all addresses; it will respond to the other commands (also
to all addresses) by reading from or writing to an array in memory. It will
quick commands to one address; it will respond to the other commands (also
to one address) by reading from or writing to an array in memory. It will
also spam the kernel logs for every command it handles.
A pointer register with auto-increment is implemented for all byte
@ -21,6 +24,11 @@ The typical use-case is like this:
3. load the target sensors chip driver module
4. observe its behavior in the kernel log
PARAMETERS:
int chip_addr:
The SMBus address to emulate a chip at.
CAVEATS:
There are independent arrays for byte/data and word/data commands. Depending
@ -33,6 +41,9 @@ If the hardware for your driver has banked registers (e.g. Winbond sensors
chips) this module will not work well - although it could be extended to
support that pretty easily.
Only one chip address is supported - although this module could be
extended to support more.
If you spam it hard enough, printk can be lossy. This module really wants
something like relayfs.

View File

@ -308,7 +308,6 @@ static struct i2c_algo_bit_data ioc_data = {
.getsda = ioc_getsda,
.getscl = ioc_getscl,
.udelay = 80,
.mdelay = 80,
.timeout = 100
};

View File

@ -293,7 +293,7 @@ static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
}
static struct i2c_algorithm acpi_ec_smbus_algorithm = {
static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
.smbus_xfer = acpi_ec_smb_access,
.functionality = acpi_ec_smb_func,
};

View File

@ -243,6 +243,7 @@ static struct i2c_driver it87_driver = {
static struct i2c_driver it87_isa_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "it87-isa",
},
.attach_adapter = it87_isa_attach_adapter,

View File

@ -175,6 +175,7 @@ static struct i2c_driver lm78_driver = {
static struct i2c_driver lm78_isa_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "lm78-isa",
},
.attach_adapter = lm78_isa_attach_adapter,

View File

@ -238,6 +238,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
static struct i2c_driver pc87360_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "pc87360",
},
.attach_adapter = pc87360_detect,

View File

@ -200,6 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
static struct i2c_driver sis5595_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "sis5595",
},
.attach_adapter = sis5595_detect,

View File

@ -228,6 +228,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter);
static struct i2c_driver smsc47b397_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "smsc47b397",
},
.attach_adapter = smsc47b397_detect,

View File

@ -128,6 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static struct i2c_driver smsc47m1_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "smsc47m1",
},
.attach_adapter = smsc47m1_detect,

View File

@ -574,6 +574,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
smbus_driver and isa_driver, and clients could be of either kind */
static struct i2c_driver via686a_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "via686a",
},
.attach_adapter = via686a_detect,

View File

@ -587,6 +587,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static struct i2c_driver vt8231_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "vt8231",
},
.attach_adapter = vt8231_detect,

View File

@ -903,6 +903,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
static struct i2c_driver w83627ehf_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "w83627ehf",
},
.attach_adapter = w83627ehf_detect,

View File

@ -339,6 +339,7 @@ static void w83627hf_init_client(struct i2c_client *client);
static struct i2c_driver w83627hf_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "w83627hf",
},
.attach_adapter = w83627hf_detect,

View File

@ -288,6 +288,7 @@ static struct i2c_driver w83781d_driver = {
static struct i2c_driver w83781d_isa_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "w83781d-isa",
},
.attach_adapter = w83781d_isa_attach_adapter,

View File

@ -1,5 +1,5 @@
#
# Character device configuration
# I2C subsystem configuration
#
menu "I2C support"

View File

@ -53,12 +53,6 @@ config I2C_ALGO8XX
tristate "MPC8xx CPM I2C interface"
depends on 8xx && I2C
config I2C_ALGO_SIBYTE
tristate "SiByte SMBus interface"
depends on SIBYTE_SB1xxx_SOC && I2C
help
Supports the SiByte SOC on-chip I2C interfaces (2 channels).
config I2C_ALGO_SGI
tristate "I2C SGI interfaces"
depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)

View File

@ -6,7 +6,6 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o
obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)

View File

@ -76,17 +76,15 @@ static inline void scllo(struct i2c_algo_bit_data *adap)
* Raise scl line, and do checking for delays. This is necessary for slower
* devices.
*/
static inline int sclhi(struct i2c_algo_bit_data *adap)
static int sclhi(struct i2c_algo_bit_data *adap)
{
unsigned long start;
setscl(adap,1);
/* Not all adapters have scl sense line... */
if (adap->getscl == NULL ) {
udelay(adap->udelay);
return 0;
}
if (!adap->getscl)
goto done;
start=jiffies;
while (! getscl(adap) ) {
@ -101,6 +99,8 @@ static inline int sclhi(struct i2c_algo_bit_data *adap)
cond_resched();
}
DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
done:
udelay(adap->udelay);
return 0;
}
@ -121,7 +121,6 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
DEBPROTO(printk(" Sr "));
setsda(adap,1);
sclhi(adap);
udelay(adap->udelay);
sdalo(adap);
scllo(adap);
@ -306,7 +305,7 @@ bailout:
* 0 chip did not answer
* -x transmission error
*/
static inline int try_address(struct i2c_adapter *i2c_adap,
static int try_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries)
{
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
@ -354,15 +353,11 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
return (retval<0)? retval : -EFAULT;
/* got a better one ?? */
}
#if 0
/* from asm/delay.h */
__delay(adap->mdelay * (loops_per_sec / 1000) );
#endif
}
return wrcount;
}
static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
{
int inval;
int rdcount=0; /* counts bytes read */
@ -412,7 +407,7 @@ static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
* -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)
static 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;
@ -517,7 +512,7 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_bit_algo = {
static const struct i2c_algorithm i2c_bit_algo = {
.master_xfer = bit_xfer,
.functionality = bit_func,
};

View File

@ -355,7 +355,7 @@ static int pca_init(struct i2c_algo_pca_data *adap)
return 0;
}
static struct i2c_algorithm pca_algo = {
static const struct i2c_algorithm pca_algo = {
.master_xfer = pca_xfer,
.functionality = pca_func,
};

View File

@ -458,7 +458,7 @@ static u32 pcf_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm pcf_algo = {
static const struct i2c_algorithm pcf_algo = {
.master_xfer = pcf_xfer,
.functionality = pcf_func,
};

View File

@ -157,7 +157,7 @@ static u32 sgi_func(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm sgi_algo = {
static const struct i2c_algorithm sgi_algo = {
.master_xfer = sgi_xfer,
.functionality = sgi_func,
};

View File

@ -1,215 +0,0 @@
/* ------------------------------------------------------------------------- */
/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 2001,2002,2003 Broadcom Corporation
Copyright (C) 1995-2000 Simon G. Vogl
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl>. */
/* Ported for SiByte SOCs by Broadcom Corporation. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_smbus.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-sibyte.h>
/* ----- global defines ----------------------------------------------- */
#define SMB_CSR(a,r) ((long)(a->reg_base + r))
/* ----- global variables --------------------------------------------- */
/* module parameters:
*/
static int bit_scan; /* have a look at what's hanging 'round */
static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data)
{
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
int data_bytes = 0;
int error;
while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
;
switch (size) {
case I2C_SMBUS_QUICK:
csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_READ) {
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
SMB_CSR(adap, R_SMB_START));
data_bytes = 1;
} else {
csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
SMB_CSR(adap, R_SMB_START));
}
break;
case I2C_SMBUS_BYTE_DATA:
csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
if (read_write == I2C_SMBUS_READ) {
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
SMB_CSR(adap, R_SMB_START));
data_bytes = 1;
} else {
csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA));
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
SMB_CSR(adap, R_SMB_START));
}
break;
case I2C_SMBUS_WORD_DATA:
csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
if (read_write == I2C_SMBUS_READ) {
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
SMB_CSR(adap, R_SMB_START));
data_bytes = 2;
} else {
csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA));
csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA));
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
SMB_CSR(adap, R_SMB_START));
}
break;
default:
return -1; /* XXXKW better error code? */
}
while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
;
error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
if (error & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
return -1; /* XXXKW better error code? */
}
if (data_bytes == 1)
data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
if (data_bytes == 2)
data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
return 0;
}
static int algo_control(struct i2c_adapter *adapter,
unsigned int cmd, unsigned long arg)
{
return 0;
}
static u32 bit_func(struct i2c_adapter *adap)
{
return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
}
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_sibyte_algo = {
.smbus_xfer = smbus_xfer,
.algo_control = algo_control, /* ioctl */
.functionality = bit_func,
};
/*
* registering functions to load algorithms at runtime
*/
int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
{
int i;
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
/* register new adapter to i2c module... */
i2c_adap->algo = &i2c_sibyte_algo;
/* Set the frequency to 100 kHz */
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
/* scan bus */
if (bit_scan) {
union i2c_smbus_data data;
int rc;
printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
i2c_adap->name);
for (i = 0x00; i < 0x7f; i++) {
/* XXXKW is this a realistic probe? */
rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
I2C_SMBUS_BYTE_DATA, &data);
if (!rc) {
printk("(%02x)",i);
} else
printk(".");
}
printk("\n");
}
return i2c_add_adapter(i2c_adap);
}
int i2c_sibyte_del_bus(struct i2c_adapter *adap)
{
int res;
if ((res = i2c_del_adapter(adap)) < 0)
return res;
return 0;
}
int __init i2c_algo_sibyte_init (void)
{
printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n");
return 0;
}
EXPORT_SYMBOL(i2c_sibyte_add_bus);
EXPORT_SYMBOL(i2c_sibyte_del_bus);
#ifdef MODULE
MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
module_param(bit_scan, int, 0);
MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
MODULE_LICENSE("GPL");
int init_module(void)
{
return i2c_algo_sibyte_init();
}
void cleanup_module(void)
{
}
#endif

View File

@ -75,11 +75,11 @@ config I2C_AMD8111
will be called i2c-amd8111.
config I2C_AU1550
tristate "Au1550 SMBus interface"
depends on I2C && SOC_AU1550
tristate "Au1550/Au1200 SMBus interface"
depends on I2C && (SOC_AU1550 || SOC_AU1200)
help
If you say yes to this option, support will be included for the
Au1550 SMBus interface.
Au1550 and Au1200 SMBus interface.
This driver can also be built as a module. If so, the module
will be called i2c-au1550.
@ -287,6 +287,16 @@ config I2C_OCORES
This driver can also be built as a module. If so, the module
will be called i2c-ocores.
config I2C_OMAP
tristate "OMAP I2C adapter"
depends on I2C && ARCH_OMAP
default y if MACH_OMAP_H3 || MACH_OMAP_OSK
help
If you say yes to this option, support will be included for the
I2C interface on the Texas Instruments OMAP1/2 family of processors.
Like OMAP1510/1610/1710/5912 and OMAP242x.
For details see http://www.ti.com/omap.
config I2C_PARPORT
tristate "Parallel port adapter"
depends on I2C && PARPORT
@ -482,19 +492,19 @@ config I2C_VIA
will be called i2c-via.
config I2C_VIAPRO
tristate "VIA 82C596/82C686/823x"
tristate "VIA 82C596/82C686/82xx"
depends on I2C && PCI
help
If you say yes to this option, support will be included for the VIA
82C596/82C686/823x I2C interfaces. Specifically, the following
82C596/82C686/82xx I2C interfaces. Specifically, the following
chipsets are supported:
82C596A/B
82C686A/B
8231
8233
8233A
8235
8237
VT82C596A/B
VT82C686A/B
VT8231
VT8233/A
VT8235
VT8237R/A
VT8251
This driver can also be built as a module. If so, the module
will be called i2c-viapro.

View File

@ -24,6 +24,7 @@ obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o

View File

@ -468,7 +468,7 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BLOCK_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = ali1535_access,
.functionality = ali1535_func,
};

View File

@ -367,7 +367,7 @@ static void ali1563_shutdown(struct pci_dev *dev)
release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
}
static struct i2c_algorithm ali1563_algorithm = {
static const struct i2c_algorithm ali1563_algorithm = {
.smbus_xfer = ali1563_access,
.functionality = ali1563_func,
};

View File

@ -463,7 +463,7 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BLOCK_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = ali15x3_access,
.functionality = ali15x3_func,
};

View File

@ -294,7 +294,7 @@ static u32 amd756_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = amd756_access,
.functionality = amd756_func,
};

View File

@ -316,7 +316,7 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = amd8111_access,
.functionality = amd8111_func,
};

View File

@ -34,8 +34,7 @@
#include <linux/errno.h>
#include <linux/i2c.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1550.h>
#include <asm/mach-au1x00/au1xxx.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
#include "i2c-au1550.h"
@ -118,13 +117,19 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
/* Reset the FIFOs, clear events.
*/
sp->psc_smbpcr = PSC_SMBPCR_DC;
stat = sp->psc_smbstat;
sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
au_sync();
do {
stat = sp->psc_smbpcr;
if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
sp->psc_smbpcr = PSC_SMBPCR_DC;
au_sync();
} while ((stat & PSC_SMBPCR_DC) != 0);
do {
stat = sp->psc_smbpcr;
au_sync();
} while ((stat & PSC_SMBPCR_DC) != 0);
udelay(50);
}
/* Write out the i2c chip address and specify operation
*/
@ -279,10 +284,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
static u32
au1550_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C;
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm au1550_algo = {
static const struct i2c_algorithm au1550_algo = {
.master_xfer = au1550_xfer,
.functionality = au1550_func,
};

View File

@ -196,7 +196,6 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
.getclock = pcf_isa_getclock,
.waitforpin = pcf_isa_waitforpin,
.udelay = 10,
.mdelay = 10,
.timeout = 100,
};

View File

@ -99,7 +99,6 @@ static struct i2c_algo_bit_data hydra_bit_data = {
.getsda = hydra_bit_getsda,
.getscl = hydra_bit_getscl,
.udelay = 5,
.mdelay = 5,
.timeout = HZ
};

View File

@ -434,7 +434,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
| (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = i801_access,
.functionality = i801_func,
};

View File

@ -166,7 +166,6 @@ static struct i2c_algo_bit_data i810_i2c_bit_data = {
.getsda = bit_i810i2c_getsda,
.getscl = bit_i810i2c_getscl,
.udelay = CYCLE_DELAY,
.mdelay = CYCLE_DELAY,
.timeout = TIMEOUT,
};
@ -182,7 +181,6 @@ static struct i2c_algo_bit_data i810_ddc_bit_data = {
.getsda = bit_i810ddc_getsda,
.getscl = bit_i810ddc_getscl,
.udelay = CYCLE_DELAY,
.mdelay = CYCLE_DELAY,
.timeout = TIMEOUT,
};

View File

@ -625,7 +625,7 @@ static u32 iic_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
}
static struct i2c_algorithm iic_algo = {
static const struct i2c_algorithm iic_algo = {
.master_xfer = iic_xfer,
.functionality = iic_func
};

View File

@ -401,7 +401,7 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm iop3xx_i2c_algo = {
static const struct i2c_algorithm iop3xx_i2c_algo = {
.master_xfer = iop3xx_i2c_master_xfer,
.algo_control = iop3xx_i2c_algo_control,
.functionality = iop3xx_i2c_func,

View File

@ -43,7 +43,7 @@
static u32 isa_func(struct i2c_adapter *adapter);
/* This is the actual algorithm we define */
static struct i2c_algorithm isa_algorithm = {
static const struct i2c_algorithm isa_algorithm = {
.functionality = isa_func,
};
@ -89,9 +89,14 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
/* Now look for clients */
driver->attach_adapter(&isa_adapter);
return 0;
res = driver->attach_adapter(&isa_adapter);
if (res) {
dev_err(&isa_adapter.dev,
"Driver %s failed to attach adapter, unregistering\n",
driver->driver.name);
driver_unregister(&driver->driver);
}
return res;
}
int i2c_isa_del_driver(struct i2c_driver *driver)
@ -125,6 +130,8 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
static int __init i2c_isa_init(void)
{
int err;
mutex_init(&isa_adapter.clist_lock);
INIT_LIST_HEAD(&isa_adapter.clients);
@ -133,8 +140,16 @@ static int __init i2c_isa_init(void)
sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
isa_adapter.dev.driver = &i2c_adapter_driver;
isa_adapter.dev.release = &i2c_adapter_dev_release;
device_register(&isa_adapter.dev);
device_create_file(&isa_adapter.dev, &dev_attr_name);
err = device_register(&isa_adapter.dev);
if (err) {
printk(KERN_ERR "i2c-isa: Failed to register device\n");
goto exit;
}
err = device_create_file(&isa_adapter.dev, &dev_attr_name);
if (err) {
printk(KERN_ERR "i2c-isa: Failed to create name file\n");
goto exit_unregister;
}
/* Add this adapter to the i2c_adapter class */
memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
@ -142,11 +157,24 @@ static int __init i2c_isa_init(void)
isa_adapter.class_dev.class = &i2c_adapter_class;
strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
BUS_ID_SIZE);
class_device_register(&isa_adapter.class_dev);
err = class_device_register(&isa_adapter.class_dev);
if (err) {
printk(KERN_ERR "i2c-isa: Failed to register class device\n");
goto exit_remove_name;
}
dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
return 0;
exit_remove_name:
device_remove_file(&isa_adapter.dev, &dev_attr_name);
exit_unregister:
init_completion(&isa_adapter.dev_released); /* Needed? */
device_unregister(&isa_adapter.dev);
wait_for_completion(&isa_adapter.dev_released);
exit:
return err;
}
static void __exit i2c_isa_exit(void)

View File

@ -114,7 +114,6 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.getsda = ixp2000_bit_getsda;
drv_data->algo_data.getscl = ixp2000_bit_getscl;
drv_data->algo_data.udelay = 6;
drv_data->algo_data.mdelay = 6;
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP2000,

View File

@ -122,7 +122,6 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.getsda = ixp4xx_bit_getsda;
drv_data->algo_data.getscl = ixp4xx_bit_getscl;
drv_data->algo_data.udelay = 10;
drv_data->algo_data.mdelay = 10;
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP4XX;

View File

@ -272,7 +272,7 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm mpc_algo = {
static const struct i2c_algorithm mpc_algo = {
.master_xfer = mpc_xfer,
.functionality = mpc_functionality,
};

View File

@ -431,7 +431,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
return num;
}
static struct i2c_algorithm mv64xxx_i2c_algo = {
static const struct i2c_algorithm mv64xxx_i2c_algo = {
.master_xfer = mv64xxx_i2c_xfer,
.functionality = mv64xxx_i2c_functionality,
};

View File

@ -109,7 +109,7 @@ static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
static u32 nforce2_func(struct i2c_adapter *adapter);
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = nforce2_access,
.functionality = nforce2_func,
};

View File

@ -199,7 +199,7 @@ static u32 ocores_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm ocores_algorithm = {
static const struct i2c_algorithm ocores_algorithm = {
.master_xfer = ocores_xfer,
.functionality = ocores_func,
};

View File

@ -0,0 +1,676 @@
/*
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
* Copyright (C) 2004 Texas Instruments.
*
* Updated to work with multiple I2C interfaces on 24xx by
* Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
*
* Cleaned up by Juha Yrjölä <juha.yrjola@nokia.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.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
#define OMAP_I2C_REV_REG 0x00
#define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18
#define OMAP_I2C_DATA_REG 0x1c
#define OMAP_I2C_SYSC_REG 0x20
#define OMAP_I2C_CON_REG 0x24
#define OMAP_I2C_OA_REG 0x28
#define OMAP_I2C_SA_REG 0x2c
#define OMAP_I2C_PSC_REG 0x30
#define OMAP_I2C_SCLL_REG 0x34
#define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
#define OMAP_I2C_IE_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */
#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */
#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
#define OMAP_I2C_STAT_AAS (1 << 9) /* Address as slave */
#define OMAP_I2C_STAT_AD0 (1 << 8) /* Address zero */
#define OMAP_I2C_STAT_XRDY (1 << 4) /* Transmit data ready */
#define OMAP_I2C_STAT_RRDY (1 << 3) /* Receive data ready */
#define OMAP_I2C_STAT_ARDY (1 << 2) /* Register access ready */
#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
#define OMAP_I2C_CON_XA (1 << 8) /* Expand address */
#define OMAP_I2C_CON_RM (1 << 2) /* Repeat mode (master only) */
#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
#define OMAP_I2C_SYSTEST_FREE (1 << 14) /* Free running mode */
#define OMAP_I2C_SYSTEST_TMODE_MASK (3 << 12) /* Test mode select */
#define OMAP_I2C_SYSTEST_TMODE_SHIFT (12) /* Test mode select */
#define OMAP_I2C_SYSTEST_SCL_I (1 << 3) /* SCL line sense in */
#define OMAP_I2C_SYSTEST_SCL_O (1 << 2) /* SCL line drive out */
#define OMAP_I2C_SYSTEST_SDA_I (1 << 1) /* SDA line sense in */
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
#endif
/* I2C System Status register (OMAP_I2C_SYSS): */
#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
/* REVISIT: Use platform_data instead of module parameters */
/* Fast Mode = 400 kHz, Standard = 100 kHz */
static int clock = 100; /* Default: 100 kHz */
module_param(clock, int, 0);
MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
struct omap_i2c_dev {
struct device *dev;
void __iomem *base; /* virtual */
int irq;
struct clk *iclk; /* Interface clock */
struct clk *fclk; /* Functional clock */
struct completion cmd_complete;
struct resource *ioarea;
u16 cmd_err;
u8 *buf;
size_t buf_len;
struct i2c_adapter adapter;
unsigned rev1:1;
};
static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
int reg, u16 val)
{
__raw_writew(val, i2c_dev->base + reg);
}
static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
{
return __raw_readw(i2c_dev->base + reg);
}
static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
dev->iclk = clk_get(dev->dev, "i2c_ick");
if (IS_ERR(dev->iclk)) {
dev->iclk = NULL;
return -ENODEV;
}
}
dev->fclk = clk_get(dev->dev, "i2c_fck");
if (IS_ERR(dev->fclk)) {
if (dev->iclk != NULL) {
clk_put(dev->iclk);
dev->iclk = NULL;
}
dev->fclk = NULL;
return -ENODEV;
}
return 0;
}
static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
{
clk_put(dev->fclk);
dev->fclk = NULL;
if (dev->iclk != NULL) {
clk_put(dev->iclk);
dev->iclk = NULL;
}
}
static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev)
{
if (dev->iclk != NULL)
clk_enable(dev->iclk);
clk_enable(dev->fclk);
}
static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
{
if (dev->iclk != NULL)
clk_disable(dev->iclk);
clk_disable(dev->fclk);
}
static int omap_i2c_init(struct omap_i2c_dev *dev)
{
u16 psc = 0;
unsigned long fclk_rate = 12000000;
unsigned long timeout;
if (!dev->rev1) {
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
OMAP_I2C_SYSS_RDONE)) {
if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting"
"for controller reset\n");
return -ETIMEDOUT;
}
msleep(1);
}
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
if (cpu_class_is_omap1()) {
struct clk *armxor_ck;
armxor_ck = clk_get(NULL, "armxor_ck");
if (IS_ERR(armxor_ck))
dev_warn(dev->dev, "Could not get armxor_ck\n");
else {
fclk_rate = clk_get_rate(armxor_ck);
clk_put(armxor_ck);
}
/* TRM for 5912 says the I2C clock must be prescaled to be
* between 7 - 12 MHz. The XOR input clock is typically
* 12, 13 or 19.2 MHz. So we should have code that produces:
*
* XOR MHz Divider Prescaler
* 12 1 0
* 13 2 1
* 19.2 2 1
*/
if (fclk_rate > 16000000)
psc = (fclk_rate + 8000000) / 12000000;
}
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
/* Program desired operating rate */
fclk_rate /= (psc + 1) * 1000;
if (psc > 2)
psc = 2;
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
fclk_rate / (clock * 2) - 7 + psc);
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
fclk_rate / (clock * 2) - 7 + psc);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
OMAP_I2C_IE_AL));
return 0;
}
/*
* Waiting on Bus Busy
*/
static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
{
unsigned long timeout;
timeout = jiffies + OMAP_I2C_TIMEOUT;
while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting for bus ready\n");
return -ETIMEDOUT;
}
msleep(1);
}
return 0;
}
/*
* Low level master read/write transaction.
*/
static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
struct i2c_msg *msg, int stop)
{
struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
int r;
u16 w;
dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
msg->addr, msg->len, msg->flags, stop);
if (msg->len == 0)
return -EINVAL;
omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
/* REVISIT: Could the STB bit of I2C_CON be used with probing? */
dev->buf = msg->buf;
dev->buf_len = msg->len;
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
init_completion(&dev->cmd_complete);
dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
if (stop)
w |= OMAP_I2C_CON_STP;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
if (r == 0) {
dev_err(dev->dev, "controller timed out\n");
omap_i2c_init(dev);
return -ETIMEDOUT;
}
if (likely(!dev->cmd_err))
return 0;
/* We have an error */
if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
OMAP_I2C_STAT_XUDF)) {
omap_i2c_init(dev);
return -EIO;
}
if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
if (msg->flags & I2C_M_IGNORE_NAK)
return 0;
if (stop) {
w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
w |= OMAP_I2C_CON_STP;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
}
return -EREMOTEIO;
}
return -EIO;
}
/*
* Prepare controller for a transaction and call omap_i2c_xfer_msg
* to do the work during IRQ processing.
*/
static int
omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
int i;
int r;
omap_i2c_enable_clocks(dev);
/* REVISIT: initialize and use adap->retries. This is an optional
* feature */
if ((r = omap_i2c_wait_for_bb(dev)) < 0)
goto out;
for (i = 0; i < num; i++) {
r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
if (r != 0)
break;
}
if (r == 0)
r = num;
out:
omap_i2c_disable_clocks(dev);
return r;
}
static u32
omap_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
}
static inline void
omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err)
{
dev->cmd_err |= err;
complete(&dev->cmd_complete);
}
static inline void
omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
{
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
static irqreturn_t
omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
{
struct omap_i2c_dev *dev = dev_id;
u16 iv, w;
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
switch (iv) {
case 0x00: /* None */
break;
case 0x01: /* Arbitration lost */
dev_err(dev->dev, "Arbitration lost\n");
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
break;
case 0x02: /* No acknowledgement */
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP);
break;
case 0x03: /* Register access ready */
omap_i2c_complete_cmd(dev, 0);
break;
case 0x04: /* Receive data ready */
if (dev->buf_len) {
w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
*dev->buf++ = w;
dev->buf_len--;
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
}
} else
dev_err(dev->dev, "RRDY IRQ while no data requested\n");
break;
case 0x05: /* Transmit data ready */
if (dev->buf_len) {
w = *dev->buf++;
dev->buf_len--;
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
}
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
} else
dev_err(dev->dev, "XRDY IRQ while no data to send\n");
break;
default:
return IRQ_NONE;
}
return IRQ_HANDLED;
}
static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
{
struct omap_i2c_dev *dev = dev_id;
u16 bits;
u16 stat, w;
int count = 0;
bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
if (count++ == 100) {
dev_warn(dev->dev, "Too much work in one IRQ\n");
break;
}
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
if (stat & OMAP_I2C_STAT_ARDY) {
omap_i2c_complete_cmd(dev, 0);
continue;
}
if (stat & OMAP_I2C_STAT_RRDY) {
w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
if (dev->buf_len) {
*dev->buf++ = w;
dev->buf_len--;
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
}
} else
dev_err(dev->dev, "RRDY IRQ while no data"
"requested\n");
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
continue;
}
if (stat & OMAP_I2C_STAT_XRDY) {
w = 0;
if (dev->buf_len) {
w = *dev->buf++;
dev->buf_len--;
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
}
} else
dev_err(dev->dev, "XRDY IRQ while no"
"data to send\n");
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
continue;
}
if (stat & OMAP_I2C_STAT_ROVR) {
dev_err(dev->dev, "Receive overrun\n");
dev->cmd_err |= OMAP_I2C_STAT_ROVR;
}
if (stat & OMAP_I2C_STAT_XUDF) {
dev_err(dev->dev, "Transmit overflow\n");
dev->cmd_err |= OMAP_I2C_STAT_XUDF;
}
if (stat & OMAP_I2C_STAT_NACK) {
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
OMAP_I2C_CON_STP);
}
if (stat & OMAP_I2C_STAT_AL) {
dev_err(dev->dev, "Arbitration lost\n");
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
}
}
return count ? IRQ_HANDLED : IRQ_NONE;
}
static const struct i2c_algorithm omap_i2c_algo = {
.master_xfer = omap_i2c_xfer,
.functionality = omap_i2c_func,
};
static int
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
int r;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?\n");
return -ENODEV;
}
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?\n");
return -ENODEV;
}
ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "I2C region already claimed\n");
return -EBUSY;
}
if (clock > 200)
clock = 400; /* Fast mode */
else
clock = 100; /* Standard mode */
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
if (!dev) {
r = -ENOMEM;
goto err_release_region;
}
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = (void __iomem *) IO_ADDRESS(mem->start);
platform_set_drvdata(pdev, dev);
if ((r = omap_i2c_get_clocks(dev)) != 0)
goto err_free_mem;
omap_i2c_enable_clocks(dev);
if (cpu_is_omap15xx())
dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
0, pdev->name, dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks;
}
r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
pdev->id, r >> 4, r & 0xf, clock);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON;
strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
adap->algo = &omap_i2c_algo;
adap->dev.parent = &pdev->dev;
/* i2c device drivers may be active on return from add_adapter() */
r = i2c_add_adapter(adap);
if (r) {
dev_err(dev->dev, "failure adding adapter\n");
goto err_free_irq;
}
omap_i2c_disable_clocks(dev);
return 0;
err_free_irq:
free_irq(dev->irq, dev);
err_unuse_clocks:
omap_i2c_disable_clocks(dev);
omap_i2c_put_clocks(dev);
err_free_mem:
platform_set_drvdata(pdev, NULL);
kfree(dev);
err_release_region:
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
release_mem_region(mem->start, (mem->end - mem->start) + 1);
return r;
}
static int
omap_i2c_remove(struct platform_device *pdev)
{
struct omap_i2c_dev *dev = platform_get_drvdata(pdev);
struct resource *mem;
platform_set_drvdata(pdev, NULL);
free_irq(dev->irq, dev);
i2c_del_adapter(&dev->adapter);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_put_clocks(dev);
kfree(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, (mem->end - mem->start) + 1);
return 0;
}
static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe,
.remove = omap_i2c_remove,
.driver = {
.name = "i2c_omap",
.owner = THIS_MODULE,
},
};
/* I2C may be needed to bring up other drivers */
static int __init
omap_i2c_init_driver(void)
{
return platform_driver_register(&omap_i2c_driver);
}
subsys_initcall(omap_i2c_init_driver);
static void __exit omap_i2c_exit_driver(void)
{
platform_driver_unregister(&omap_i2c_driver);
}
module_exit(omap_i2c_exit_driver);
MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
MODULE_LICENSE("GPL");

View File

@ -103,7 +103,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
.getsda = parport_getsda,
.getscl = parport_getscl,
.udelay = 50,
.mdelay = 50,
.timeout = HZ,
};

View File

@ -138,7 +138,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
.getsda = parport_getsda,
.getscl = parport_getscl,
.udelay = 60,
.mdelay = 60,
.timeout = HZ,
};

View File

@ -376,7 +376,7 @@ static u32 piix4_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BLOCK_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = piix4_access,
.functionality = piix4_func,
};

View File

@ -175,7 +175,7 @@ static u32 i2c_powermac_func(struct i2c_adapter * adapter)
}
/* For now, we only handle smbus */
static struct i2c_algorithm i2c_powermac_algorithm = {
static const struct i2c_algorithm i2c_powermac_algorithm = {
.smbus_xfer = i2c_powermac_smbus_xfer,
.master_xfer = i2c_powermac_master_xfer,
.functionality = i2c_powermac_func,

View File

@ -180,7 +180,6 @@ static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iom
p->algo.getsda = bit_s3via_getsda;
p->algo.getscl = bit_s3via_getscl;
p->algo.udelay = CYCLE_DELAY;
p->algo.mdelay = CYCLE_DELAY;
p->algo.timeout = TIMEOUT;
p->algo.data = p;
p->mmvga = mmvga;

View File

@ -926,7 +926,7 @@ static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm i2c_pxa_algorithm = {
static const struct i2c_algorithm i2c_pxa_algorithm = {
.master_xfer = i2c_pxa_xfer,
.functionality = i2c_pxa_functionality,
};

View File

@ -566,7 +566,7 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
/* i2c bus registration info */
static struct i2c_algorithm s3c24xx_i2c_algorithm = {
static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.master_xfer = s3c24xx_i2c_xfer,
.functionality = s3c24xx_i2c_func,
};

View File

@ -140,7 +140,6 @@ static struct i2c_algo_bit_data sav_i2c_bit_data = {
.getsda = bit_savi2c_getsda,
.getscl = bit_savi2c_getscl,
.udelay = CYCLE_DELAY,
.mdelay = CYCLE_DELAY,
.timeout = TIMEOUT
};

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2004 Steven J. Hill
* Copyright (C) 2001,2002,2003 Broadcom Corporation
* Copyright (C) 1995-2000 Simon G. Vogl
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,11 +18,162 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c-algo-sibyte.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_smbus.h>
struct i2c_algo_sibyte_data {
void *data; /* private data */
int bus; /* which bus */
void *reg_base; /* CSR base */
};
/* ----- global defines ----------------------------------------------- */
#define SMB_CSR(a,r) ((long)(a->reg_base + r))
/* ----- global variables --------------------------------------------- */
/* module parameters:
*/
static int bit_scan; /* have a look at what's hanging 'round */
module_param(bit_scan, int, 0);
MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data)
{
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
int data_bytes = 0;
int error;
while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
;
switch (size) {
case I2C_SMBUS_QUICK:
csr_out32((V_SMB_ADDR(addr) |
(read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_READ) {
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
SMB_CSR(adap, R_SMB_START));
data_bytes = 1;
} else {
csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
SMB_CSR(adap, R_SMB_START));
}
break;
case I2C_SMBUS_BYTE_DATA:
csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
if (read_write == I2C_SMBUS_READ) {
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
SMB_CSR(adap, R_SMB_START));
data_bytes = 1;
} else {
csr_out32(V_SMB_LB(data->byte),
SMB_CSR(adap, R_SMB_DATA));
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
SMB_CSR(adap, R_SMB_START));
}
break;
case I2C_SMBUS_WORD_DATA:
csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
if (read_write == I2C_SMBUS_READ) {
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
SMB_CSR(adap, R_SMB_START));
data_bytes = 2;
} else {
csr_out32(V_SMB_LB(data->word & 0xff),
SMB_CSR(adap, R_SMB_DATA));
csr_out32(V_SMB_MB(data->word >> 8),
SMB_CSR(adap, R_SMB_DATA));
csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
SMB_CSR(adap, R_SMB_START));
}
break;
default:
return -1; /* XXXKW better error code? */
}
while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
;
error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
if (error & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
return -1; /* XXXKW better error code? */
}
if (data_bytes == 1)
data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
if (data_bytes == 2)
data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
return 0;
}
static u32 bit_func(struct i2c_adapter *adap)
{
return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
}
/* -----exported algorithm data: ------------------------------------- */
static const struct i2c_algorithm i2c_sibyte_algo = {
.smbus_xfer = smbus_xfer,
.functionality = bit_func,
};
/*
* registering functions to load algorithms at runtime
*/
int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
{
int i;
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
/* register new adapter to i2c module... */
i2c_adap->algo = &i2c_sibyte_algo;
/* Set the frequency to 100 kHz */
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
/* scan bus */
if (bit_scan) {
union i2c_smbus_data data;
int rc;
printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
i2c_adap->name);
for (i = 0x00; i < 0x7f; i++) {
/* XXXKW is this a realistic probe? */
rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
I2C_SMBUS_BYTE_DATA, &data);
if (!rc) {
printk("(%02x)",i);
} else
printk(".");
}
printk("\n");
}
return i2c_add_adapter(i2c_adap);
}
static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
{ NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
{ NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
@ -58,13 +210,13 @@ static int __init i2c_sibyte_init(void)
static void __exit i2c_sibyte_exit(void)
{
i2c_sibyte_del_bus(&sibyte_board_adapter[0]);
i2c_sibyte_del_bus(&sibyte_board_adapter[1]);
i2c_del_bus(&sibyte_board_adapter[0]);
i2c_del_bus(&sibyte_board_adapter[1]);
}
module_init(i2c_sibyte_init);
module_exit(i2c_sibyte_exit);
MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>");
MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>");
MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
MODULE_LICENSE("GPL");

View File

@ -358,7 +358,7 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_PROC_CALL;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = sis5595_access,
.functionality = sis5595_func,
};

View File

@ -450,7 +450,7 @@ exit:
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = sis630_access,
.functionality = sis630_func,
};

View File

@ -242,7 +242,7 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_PROC_CALL;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = sis96x_access,
.functionality = sis96x_func,
};

View File

@ -27,6 +27,10 @@
#include <linux/errno.h>
#include <linux/i2c.h>
static unsigned short chip_addr;
module_param(chip_addr, ushort, S_IRUGO);
MODULE_PARM_DESC(chip_addr, "Chip address (between 0x03 and 0x77)\n");
static u8 stub_pointer;
static u8 stub_bytes[256];
static u16 stub_words[256];
@ -37,6 +41,9 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
{
s32 ret;
if (addr != chip_addr)
return -ENODEV;
switch (size) {
case I2C_SMBUS_QUICK:
@ -108,7 +115,7 @@ static u32 stub_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.functionality = stub_func,
.smbus_xfer = stub_xfer,
};
@ -122,7 +129,17 @@ static struct i2c_adapter stub_adapter = {
static int __init i2c_stub_init(void)
{
printk(KERN_INFO "i2c-stub loaded\n");
if (!chip_addr) {
printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
return -ENODEV;
}
if (chip_addr < 0x03 || chip_addr > 0x77) {
printk(KERN_ERR "i2c-stub: Invalid chip address 0x%02x\n",
chip_addr);
return -EINVAL;
}
printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", chip_addr);
return i2c_add_adapter(&stub_adapter);
}

View File

@ -81,7 +81,6 @@ static struct i2c_algo_bit_data bit_data = {
.getsda = bit_via_getsda,
.getscl = bit_via_getscl,
.udelay = 5,
.mdelay = 5,
.timeout = HZ
};

View File

@ -34,6 +34,8 @@
VT8233A 0x3147 yes?
VT8235 0x3177 yes
VT8237R 0x3227 yes
VT8237A 0x3337 yes
VT8251 0x3287 yes
Note: we assume there can only be one device, with one SMBus interface.
*/
@ -297,7 +299,7 @@ static u32 vt596_func(struct i2c_adapter *adapter)
return func;
}
static struct i2c_algorithm smbus_algorithm = {
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = vt596_access,
.functionality = vt596_func,
};
@ -381,7 +383,9 @@ found:
dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
switch (pdev->device) {
case PCI_DEVICE_ID_VIA_8251:
case PCI_DEVICE_ID_VIA_8237:
case PCI_DEVICE_ID_VIA_8237A:
case PCI_DEVICE_ID_VIA_8235:
case PCI_DEVICE_ID_VIA_8233A:
case PCI_DEVICE_ID_VIA_8233_0:
@ -432,8 +436,12 @@ static struct pci_device_id vt596_ids[] = {
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
.driver_data = SMBBA1 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
.driver_data = SMBBA3 },
{ 0, }
};

View File

@ -160,7 +160,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
.getsda = bit_vooi2c_getsda,
.getscl = bit_vooi2c_getscl,
.udelay = CYCLE_DELAY,
.mdelay = CYCLE_DELAY,
.timeout = TIMEOUT
};
@ -177,7 +176,6 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
.getsda = bit_vooddc_getsda,
.getscl = bit_vooddc_getscl,
.udelay = CYCLE_DELAY,
.mdelay = CYCLE_DELAY,
.timeout = TIMEOUT
};

View File

@ -383,7 +383,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
}
/* For now, we only handle combined mode (smbus) */
static struct i2c_algorithm scx200_acb_algorithm = {
static const struct i2c_algorithm scx200_acb_algorithm = {
.smbus_xfer = scx200_acb_smbus_xfer,
.functionality = scx200_acb_func,
};

View File

@ -71,12 +71,12 @@ static int scx200_i2c_getsda(void *data)
*/
static struct i2c_algo_bit_data scx200_i2c_data = {
NULL,
scx200_i2c_setsda,
scx200_i2c_setscl,
scx200_i2c_getsda,
scx200_i2c_getscl,
10, 10, 100, /* waits, timeout */
.setsda = scx200_i2c_setsda,
.setscl = scx200_i2c_setscl,
.getsda = scx200_i2c_getsda,
.getscl = scx200_i2c_getscl,
.udelay = 10,
.timeout = 100,
};
static struct i2c_adapter scx200_i2c_ops = {

View File

@ -209,10 +209,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* create the sysfs eeprom file */
sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
if (err)
goto exit_detach;
return 0;
exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
@ -223,6 +227,8 @@ static int eeprom_detach_client(struct i2c_client *client)
{
int err;
sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
err = i2c_detach_client(client);
if (err)
return err;

View File

@ -199,8 +199,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
mutex_init(&data->update_lock);
/* Init fake client data */
/* set the client data to the i2c_client so that it will get freed */
i2c_set_clientdata(fake_client, fake_client);
i2c_set_clientdata(fake_client, NULL);
fake_client->addr = address | 1;
fake_client->adapter = adapter;
fake_client->driver = &max6875_driver;
@ -214,13 +213,17 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_kfree2;
if ((err = i2c_attach_client(fake_client)) != 0)
goto exit_detach;
goto exit_detach1;
sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
if (err)
goto exit_detach2;
return 0;
exit_detach:
exit_detach2:
i2c_detach_client(fake_client);
exit_detach1:
i2c_detach_client(real_client);
exit_kfree2:
kfree(fake_client);
@ -229,14 +232,24 @@ exit_kfree1:
return err;
}
/* Will be called for both the real client and the fake client */
static int max6875_detach_client(struct i2c_client *client)
{
int err;
struct max6875_data *data = i2c_get_clientdata(client);
/* data is NULL for the fake client */
if (data)
sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
err = i2c_detach_client(client);
if (err)
return err;
kfree(i2c_get_clientdata(client));
if (data) /* real client */
kfree(data);
else /* fake client */
kfree(client);
return 0;
}

View File

@ -148,11 +148,16 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(new_client)))
goto exit_kfree;
/* Register sysfs hooks (don't care about failure) */
sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
/* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj,
&pca9539_defattr_group);
if (err)
goto exit_detach;
return 0;
exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
@ -163,6 +168,8 @@ static int pca9539_detach_client(struct i2c_client *client)
{
int err;
sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
if ((err = i2c_detach_client(client)))
return err;

View File

@ -105,6 +105,16 @@ static ssize_t set_write(struct device *dev, struct device_attribute *attr, cons
static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
static struct attribute *pcf8574_attributes[] = {
&dev_attr_read.attr,
&dev_attr_write.attr,
NULL
};
static const struct attribute_group pcf8574_attr_group = {
.attrs = pcf8574_attributes,
};
/*
* Real code
*/
@ -166,13 +176,13 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
pcf8574_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_read);
device_create_file(&new_client->dev, &dev_attr_write);
err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group);
if (err)
goto exit_detach;
return 0;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
exit_detach:
i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@ -183,6 +193,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
{
int err;
sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
if ((err = i2c_detach_client(client)))
return err;

View File

@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
show_out0_enable, set_out0_enable);
static struct attribute *pcf8591_attributes[] = {
&dev_attr_out0_enable.attr,
&dev_attr_out0_output.attr,
&dev_attr_in0_input.attr,
&dev_attr_in1_input.attr,
NULL
};
static const struct attribute_group pcf8591_attr_group = {
.attrs = pcf8591_attributes,
};
static struct attribute *pcf8591_attributes_opt[] = {
&dev_attr_in2_input.attr,
&dev_attr_in3_input.attr,
NULL
};
static const struct attribute_group pcf8591_attr_group_opt = {
.attrs = pcf8591_attributes_opt,
};
/*
* Real code
*/
@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
pcf8591_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_out0_enable);
device_create_file(&new_client->dev, &dev_attr_out0_output);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
if (err)
goto exit_detach;
/* Register input2 if not in "two differential inputs" mode */
if (input_mode != 3 )
device_create_file(&new_client->dev, &dev_attr_in2_input);
/* Register input3 only in "four single ended inputs" mode */
if (input_mode == 0)
device_create_file(&new_client->dev, &dev_attr_in3_input);
return 0;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
if (input_mode != 3) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_in2_input)))
goto exit_sysfs_remove;
}
/* Register input3 only in "four single ended inputs" mode */
if (input_mode == 0) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_in3_input)))
goto exit_sysfs_remove;
}
return 0;
exit_sysfs_remove:
sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client)
{
int err;
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
if ((err = i2c_detach_client(client)))
return err;

View File

@ -183,15 +183,21 @@ int i2c_add_adapter(struct i2c_adapter *adap)
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
adap->dev.driver = &i2c_adapter_driver;
adap->dev.release = &i2c_adapter_dev_release;
device_register(&adap->dev);
device_create_file(&adap->dev, &dev_attr_name);
res = device_register(&adap->dev);
if (res)
goto out_list;
res = device_create_file(&adap->dev, &dev_attr_name);
if (res)
goto out_unregister;
/* Add this adapter to the i2c_adapter class */
memset(&adap->class_dev, 0x00, sizeof(struct class_device));
adap->class_dev.dev = &adap->dev;
adap->class_dev.class = &i2c_adapter_class;
strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
class_device_register(&adap->class_dev);
res = class_device_register(&adap->class_dev);
if (res)
goto out_remove_name;
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
@ -206,6 +212,17 @@ int i2c_add_adapter(struct i2c_adapter *adap)
out_unlock:
mutex_unlock(&core_lists);
return res;
out_remove_name:
device_remove_file(&adap->dev, &dev_attr_name);
out_unregister:
init_completion(&adap->dev_released); /* Needed? */
device_unregister(&adap->dev);
wait_for_completion(&adap->dev_released);
out_list:
list_del(&adap->list);
idr_remove(&i2c_adapter_idr, adap->nr);
goto out_unlock;
}
@ -394,14 +411,14 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
int i2c_attach_client(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
int res = 0;
mutex_lock(&adapter->clist_lock);
if (__i2c_check_addr(client->adapter, client->addr)) {
mutex_unlock(&adapter->clist_lock);
return -EBUSY;
res = -EBUSY;
goto out_unlock;
}
list_add_tail(&client->list,&adapter->clients);
mutex_unlock(&adapter->clist_lock);
if (adapter->client_register) {
if (adapter->client_register(client)) {
@ -422,10 +439,26 @@ int i2c_attach_client(struct i2c_client *client)
"%d-%04x", i2c_adapter_id(adapter), client->addr);
dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
client->name, client->dev.bus_id);
device_register(&client->dev);
device_create_file(&client->dev, &dev_attr_client_name);
return 0;
res = device_register(&client->dev);
if (res)
goto out_list;
res = device_create_file(&client->dev, &dev_attr_client_name);
if (res)
goto out_unregister;
out_unlock:
mutex_unlock(&adapter->clist_lock);
return res;
out_unregister:
init_completion(&client->released); /* Needed? */
device_unregister(&client->dev);
wait_for_completion(&client->released);
out_list:
list_del(&client->list);
dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
"(%d)\n", client->name, client->addr, res);
goto out_unlock;
}
@ -674,11 +707,16 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
/* Finally call the custom detection function */
err = found_proc(adapter, addr, kind);
/* -ENODEV can be returned if there is a chip at the given address
but it isn't supported by this chip driver. We catch it here as
this isn't an error. */
return (err == -ENODEV) ? 0 : err;
if (err == -ENODEV)
err = 0;
if (err)
dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n",
addr, err);
return err;
}
int i2c_probe(struct i2c_adapter *adapter,
@ -868,7 +906,7 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
return -1;
else
return 0x0FF & data.byte;
return data.byte;
}
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
@ -884,7 +922,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
return -1;
else
return 0x0FF & data.byte;
return data.byte;
}
s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
@ -903,7 +941,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
return -1;
else
return 0x0FFFF & data.word;
return data.word;
}
s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
@ -1006,7 +1044,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
else {
msg[0].len=3;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
msgbuf0[2] = data->word >> 8;
}
break;
case I2C_SMBUS_PROC_CALL:
@ -1015,7 +1053,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
msg[0].len = 3;
msg[1].len = 2;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
msgbuf0[2] = data->word >> 8;
break;
case I2C_SMBUS_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {

View File

@ -32,43 +32,35 @@
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
static struct i2c_client i2cdev_client_template;
static struct i2c_driver i2cdev_driver;
struct i2c_dev {
int minor;
struct list_head list;
struct i2c_adapter *adap;
struct class_device *class_dev;
};
#define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
#define I2C_MINORS 256
static struct i2c_dev *i2c_dev_array[I2C_MINORS];
static DEFINE_SPINLOCK(i2c_dev_array_lock);
static LIST_HEAD(i2c_dev_list);
static DEFINE_SPINLOCK(i2c_dev_list_lock);
static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
{
struct i2c_dev *i2c_dev;
spin_lock(&i2c_dev_array_lock);
i2c_dev = i2c_dev_array[index];
spin_unlock(&i2c_dev_array_lock);
return i2c_dev;
}
static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev = NULL;
spin_lock(&i2c_dev_array_lock);
if ((i2c_dev_array[adap->nr]) &&
(i2c_dev_array[adap->nr]->adap == adap))
i2c_dev = i2c_dev_array[adap->nr];
spin_unlock(&i2c_dev_array_lock);
spin_lock(&i2c_dev_list_lock);
list_for_each_entry(i2c_dev, &i2c_dev_list, list) {
if (i2c_dev->adap->nr == index)
goto found;
}
i2c_dev = NULL;
found:
spin_unlock(&i2c_dev_list_lock);
return i2c_dev;
}
@ -76,30 +68,28 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
if (adap->nr >= I2C_MINORS) {
printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",
adap->nr);
return ERR_PTR(-ENODEV);
}
i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev)
return ERR_PTR(-ENOMEM);
i2c_dev->adap = adap;
spin_lock(&i2c_dev_array_lock);
if (i2c_dev_array[adap->nr]) {
spin_unlock(&i2c_dev_array_lock);
dev_err(&adap->dev, "i2c-dev already has a device assigned to this adapter\n");
goto error;
}
i2c_dev->minor = adap->nr;
i2c_dev_array[adap->nr] = i2c_dev;
spin_unlock(&i2c_dev_array_lock);
spin_lock(&i2c_dev_list_lock);
list_add_tail(&i2c_dev->list, &i2c_dev_list);
spin_unlock(&i2c_dev_list_lock);
return i2c_dev;
error:
kfree(i2c_dev);
return ERR_PTR(-ENODEV);
}
static void return_i2c_dev(struct i2c_dev *i2c_dev)
{
spin_lock(&i2c_dev_array_lock);
i2c_dev_array[i2c_dev->minor] = NULL;
spin_unlock(&i2c_dev_array_lock);
spin_lock(&i2c_dev_list_lock);
list_del(&i2c_dev->list);
spin_unlock(&i2c_dev_list_lock);
}
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
@ -375,12 +365,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
if (!adap)
return -ENODEV;
client = kmalloc(sizeof(*client), GFP_KERNEL);
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client) {
i2c_put_adapter(adap);
return -ENOMEM;
}
memcpy(client, &i2cdev_client_template, sizeof(*client));
snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
client->driver = &i2cdev_driver;
/* registered with adapter, passed as client to user */
client->adapter = adap;
@ -415,41 +406,47 @@ static struct class *i2c_dev_class;
static int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
struct device *dev;
int res;
i2c_dev = get_free_i2c_dev(adap);
if (IS_ERR(i2c_dev))
return PTR_ERR(i2c_dev);
pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
adap->name, i2c_dev->minor);
/* register this i2c device with the driver core */
i2c_dev->adap = adap;
dev = &adap->dev;
i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
MKDEV(I2C_MAJOR, i2c_dev->minor),
dev, "i2c-%d", i2c_dev->minor);
if (!i2c_dev->class_dev)
MKDEV(I2C_MAJOR, adap->nr),
&adap->dev, "i2c-%d",
adap->nr);
if (!i2c_dev->class_dev) {
res = -ENODEV;
goto error;
class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
}
res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
if (res)
goto error_destroy;
pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
adap->name, adap->nr);
return 0;
error_destroy:
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error:
return_i2c_dev(i2c_dev);
kfree(i2c_dev);
return -ENODEV;
return res;
}
static int i2cdev_detach_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
i2c_dev = i2c_dev_get_by_adapter(adap);
if (!i2c_dev)
return -ENODEV;
i2c_dev = i2c_dev_get_by_minor(adap->nr);
if (!i2c_dev) /* attach_adapter must have failed */
return 0;
class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
return_i2c_dev(i2c_dev);
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@ -471,12 +468,6 @@ static struct i2c_driver i2cdev_driver = {
.detach_client = i2cdev_detach_client,
};
static struct i2c_client i2cdev_client_template = {
.name = "I2C /dev entry",
.addr = -1,
.driver = &i2cdev_driver,
};
static int __init i2c_dev_init(void)
{
int res;

View File

@ -137,7 +137,6 @@ static struct i2c_algo_bit_data bit_data = {
.getsda = bit_getsda,
.getscl = bit_getscl,
.udelay = 5,
.mdelay = 5,
.timeout = 100,
};

View File

@ -100,7 +100,6 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
.getsda = bttv_bit_getsda,
.getscl = bttv_bit_getscl,
.udelay = 16,
.mdelay = 10,
.timeout = 200,
};

View File

@ -155,7 +155,6 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
.getsda = cx8800_bit_getsda,
.getscl = cx8800_bit_getscl,
.udelay = 16,
.mdelay = 10,
.timeout = 200,
};

View File

@ -100,7 +100,6 @@ static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
.getsda = vp3054_bit_getsda,
.getscl = vp3054_bit_getscl,
.udelay = 16,
.mdelay = 10,
.timeout = 200,
};

View File

@ -820,7 +820,6 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
.getsda = zoran_i2c_getsda,
.getscl = zoran_i2c_getscl,
.udelay = 10,
.mdelay = 0,
.timeout = 100,
};

View File

@ -98,7 +98,6 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
chan->algo.getsda = i810i2c_getsda;
chan->algo.getscl = i810i2c_getscl;
chan->algo.udelay = 10;
chan->algo.mdelay = 10;
chan->algo.timeout = (HZ/2);
chan->algo.data = chan;

View File

@ -95,12 +95,12 @@ static struct i2c_adapter matrox_i2c_adapter_template =
static struct i2c_algo_bit_data matrox_i2c_algo_template =
{
NULL,
matroxfb_gpio_setsda,
matroxfb_gpio_setscl,
matroxfb_gpio_getsda,
matroxfb_gpio_getscl,
10, 10, 100,
.setsda = matroxfb_gpio_setsda,
.setscl = matroxfb_gpio_setscl,
.getsda = matroxfb_gpio_getsda,
.getscl = matroxfb_gpio_getscl,
.udelay = 10,
.timeout = 100,
};
static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,

View File

@ -148,7 +148,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pcidev->dev;
chan->algo.udelay = 40;
chan->algo.mdelay = 5;
chan->algo.timeout = 20;
chan->algo.data = chan;

View File

@ -40,7 +40,6 @@ struct i2c_algo_bit_data {
/* local settings */
int udelay; /* half-clock-cycle time in microsecs */
/* i.e. clock is (500 / udelay) KHz */
int mdelay; /* in millisecs, unused */
int timeout; /* in jiffies */
};

View File

@ -35,7 +35,6 @@ struct i2c_algo_pcf_data {
/* local settings */
int udelay;
int mdelay;
int timeout;
};

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2001,2002,2003 Broadcom Corporation
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef I2C_ALGO_SIBYTE_H
#define I2C_ALGO_SIBYTE_H 1
#include <linux/i2c.h>
struct i2c_algo_sibyte_data {
void *data; /* private data */
int bus; /* which bus */
void *reg_base; /* CSR base */
};
int i2c_sibyte_add_bus(struct i2c_adapter *, int speed);
int i2c_sibyte_del_bus(struct i2c_adapter *);
#endif /* I2C_ALGO_SIBYTE_H */

View File

@ -64,14 +64,6 @@ extern int i2c_master_recv(struct i2c_client *,char* ,int);
*/
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
/*
* Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor.
* This is not tested/implemented yet and will change in the future.
*/
extern int i2c_slave_send(struct i2c_client *,char*,int);
extern int i2c_slave_recv(struct i2c_client *,char*,int);
/* This is the very generalized SMBus access routine. You probably do not
want to use this, though; one of the functions below may be much easier,
@ -201,10 +193,6 @@ struct i2c_algorithm {
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data);
/* --- these optional/future use for some adapter types.*/
int (*slave_send)(struct i2c_adapter *,char*,int);
int (*slave_recv)(struct i2c_adapter *,char*,int);
/* --- ioctl like call to set div. parameters. */
int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
@ -220,7 +208,7 @@ struct i2c_adapter {
struct module *owner;
unsigned int id;
unsigned int class;
struct i2c_algorithm *algo;/* the algorithm to access the bus */
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
void *algo_data;
/* --- administration stuff. */