2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-11-20 16:46:23 +08:00

Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: (56 commits)
  i2c: Add detection capability to new-style drivers
  i2c: Call client_unregister for new-style devices too
  i2c: Clean up old chip drivers
  i2c-ibm_iic: Register child nodes
  i2c: New-style EEPROM driver using device IDs
  i2c: Export the i2c_bus_type symbol
  i2c-au1550: Fix PM support
  i2c-dev: Delete empty detach_client callback
  i2c: Drop stray references to lm_sensors
  i2c: Check for ACPI resource conflicts
  i2c-ocores: basic PM support
  i2c-sibyte: SWARM I2C board initialization
  i2c-i801: Fix handling of error conditions
  i2c-i801: Rename local variable temp to status
  i2c-i801: Properly report bus arbitration loss
  i2c-i801: Remove verbose debugging messages
  i2c-algo-pcf: Drop unused struct members
  i2c-algo-pcf: Multi-master lost-arbitration improvement
  i2c: Deprecate the legacy gpio drivers
  i2c-pxa: Initialize early
  ...
This commit is contained in:
Linus Torvalds 2008-07-15 11:16:05 -07:00
commit dc221eae08
72 changed files with 3897 additions and 2261 deletions

View File

@ -222,13 +222,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
--------------------------- ---------------------------
What: i2c-i810, i2c-prosavage and i2c-savage4
When: May 2008
Why: These drivers are superseded by i810fb, intelfb and savagefb.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
What (Why): What (Why):
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
(superseded by xt_TOS/xt_tos target & match) (superseded by xt_TOS/xt_tos target & match)

View File

@ -1,47 +0,0 @@
Kernel driver i2c-i810
Supported adapters:
* Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
* Intel 82845G (GMCH)
Authors:
Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
Kyösti Mälkki <kmalkki@cc.hut.fi>,
Ralph Metzler <rjkm@thp.uni-koeln.de>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
Main contact: Mark Studebaker <mdsxyz123@yahoo.com>
Description
-----------
WARNING: If you have an '810' or '815' motherboard, your standard I2C
temperature sensors are most likely on the 801's I2C bus. You want the
i2c-i801 driver for those, not this driver.
Now for the i2c-i810...
The GMCH chip contains two I2C interfaces.
The first interface is used for DDC (Data Display Channel) which is a
serial channel through the VGA monitor connector to a DDC-compliant
monitor. This interface is defined by the Video Electronics Standards
Association (VESA). The standards are available for purchase at
http://www.vesa.org .
The second interface is a general-purpose I2C bus. It may be connected to a
TV-out chip such as the BT869 or possibly to a digital flat-panel display.
Features
--------
Both busses use the i2c-algo-bit driver for 'bit banging'
and support for specific transactions is provided by i2c-algo-bit.
Issues
------
If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1),
the test may fail; if so, the i2c-i810 driver won't be inserted. However,
we think this has been fixed.

View File

@ -1,23 +0,0 @@
Kernel driver i2c-prosavage
Supported adapters:
S3/VIA KM266/VT8375 aka ProSavage8
S3/VIA KM133/VT8365 aka Savage4
Author: Henk Vergonet <henk@god.dyndns.org>
Description
-----------
The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or
'host').
The first interface is used for DDC (Data Display Channel) which is a
serial channel through the VGA monitor connector to a DDC-compliant
monitor. This interface is defined by the Video Electronics Standards
Association (VESA). The standards are available for purchase at
http://www.vesa.org . The second interface is a general-purpose I2C bus.
Usefull for gaining access to the TV Encoder chips.

View File

@ -1,26 +0,0 @@
Kernel driver i2c-savage4
Supported adapters:
* Savage4
* Savage2000
Authors:
Alexander Wold <awold@bigfoot.com>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
Description
-----------
The Savage4 chips contain two I2C interfaces (aka a I2C 'master'
or 'host').
The first interface is used for DDC (Data Display Channel) which is a
serial channel through the VGA monitor connector to a DDC-compliant
monitor. This interface is defined by the Video Electronics Standards
Association (VESA). The standards are available for purchase at
http://www.vesa.org . The DDC bus is not yet supported because its register
is not directly memory-mapped.
The second interface is a general-purpose I2C bus. This is the only
interface supported by the driver at the moment.

View File

@ -0,0 +1,127 @@
This is a summary of the most important conventions for use of fault
codes in the I2C/SMBus stack.
A "Fault" is not always an "Error"
----------------------------------
Not all fault reports imply errors; "page faults" should be a familiar
example. Software often retries idempotent operations after transient
faults. There may be fancier recovery schemes that are appropriate in
some cases, such as re-initializing (and maybe resetting). After such
recovery, triggered by a fault report, there is no error.
In a similar way, sometimes a "fault" code just reports one defined
result for an operation ... it doesn't indicate that anything is wrong
at all, just that the outcome wasn't on the "golden path".
In short, your I2C driver code may need to know these codes in order
to respond correctly. Other code may need to rely on YOUR code reporting
the right fault code, so that it can (in turn) behave correctly.
I2C and SMBus fault codes
-------------------------
These are returned as negative numbers from most calls, with zero or
some positive number indicating a non-fault return. The specific
numbers associated with these symbols differ between architectures,
though most Linux systems use <asm-generic/errno*.h> numbering.
Note that the descriptions here are not exhaustive. There are other
codes that may be returned, and other cases where these codes should
be returned. However, drivers should not return other codes for these
cases (unless the hardware doesn't provide unique fault reports).
Also, codes returned by adapter probe methods follow rules which are
specific to their host bus (such as PCI, or the platform bus).
EAGAIN
Returned by I2C adapters when they lose arbitration in master
transmit mode: some other master was transmitting different
data at the same time.
Also returned when trying to invoke an I2C operation in an
atomic context, when some task is already using that I2C bus
to execute some other operation.
EBADMSG
Returned by SMBus logic when an invalid Packet Error Code byte
is received. This code is a CRC covering all bytes in the
transaction, and is sent before the terminating STOP. This
fault is only reported on read transactions; the SMBus slave
may have a way to report PEC mismatches on writes from the
host. Note that even if PECs are in use, you should not rely
on these as the only way to detect incorrect data transfers.
EBUSY
Returned by SMBus adapters when the bus was busy for longer
than allowed. This usually indicates some device (maybe the
SMBus adapter) needs some fault recovery (such as resetting),
or that the reset was attempted but failed.
EINVAL
This rather vague error means an invalid parameter has been
detected before any I/O operation was started. Use a more
specific fault code when you can.
One example would be a driver trying an SMBus Block Write
with block size outside the range of 1-32 bytes.
EIO
This rather vague error means something went wrong when
performing an I/O operation. Use a more specific fault
code when you can.
ENODEV
Returned by driver probe() methods. This is a bit more
specific than ENXIO, implying the problem isn't with the
address, but with the device found there. Driver probes
may verify the device returns *correct* responses, and
return this as appropriate. (The driver core will warn
about probe faults other than ENXIO and ENODEV.)
ENOMEM
Returned by any component that can't allocate memory when
it needs to do so.
ENXIO
Returned by I2C adapters to indicate that the address phase
of a transfer didn't get an ACK. While it might just mean
an I2C device was temporarily not responding, usually it
means there's nothing listening at that address.
Returned by driver probe() methods to indicate that they
found no device to bind to. (ENODEV may also be used.)
EOPNOTSUPP
Returned by an adapter when asked to perform an operation
that it doesn't, or can't, support.
For example, this would be returned when an adapter that
doesn't support SMBus block transfers is asked to execute
one. In that case, the driver making that request should
have verified that functionality was supported before it
made that block transfer request.
Similarly, if an I2C adapter can't execute all legal I2C
messages, it should return this when asked to perform a
transaction it can't. (These limitations can't be seen in
the adapter's functionality mask, since the assumption is
that if an adapter supports I2C it supports all of I2C.)
EPROTO
Returned when slave does not conform to the relevant I2C
or SMBus (or chip-specific) protocol specifications. One
case is when the length of an SMBus block data response
(from the SMBus slave) is outside the range 1-32 bytes.
ETIMEDOUT
This is returned by drivers when an operation took too much
time, and was aborted before it completed.
SMBus adapters may return it when an operation took more
time than allowed by the SMBus specification; for example,
when a slave stretches clocks too far. I2C has no such
timeouts, but it's normal for I2C adapters to impose some
arbitrary limits (much longer than SMBus!) too.

View File

@ -42,8 +42,8 @@ Count (8 bits): A data byte containing the length of a block operation.
[..]: Data sent by I2C device, as opposed to data sent by the host adapter. [..]: Data sent by I2C device, as opposed to data sent by the host adapter.
SMBus Quick Command: i2c_smbus_write_quick() SMBus Quick Command
============================================= ===================
This sends a single bit to the device, at the place of the Rd/Wr bit. This sends a single bit to the device, at the place of the Rd/Wr bit.

View File

@ -44,6 +44,10 @@ static struct i2c_driver foo_driver = {
.id_table = foo_ids, .id_table = foo_ids,
.probe = foo_probe, .probe = foo_probe,
.remove = foo_remove, .remove = foo_remove,
/* if device autodetection is needed: */
.class = I2C_CLASS_SOMETHING,
.detect = foo_detect,
.address_data = &addr_data,
/* else, driver uses "legacy" binding model: */ /* else, driver uses "legacy" binding model: */
.attach_adapter = foo_attach_adapter, .attach_adapter = foo_attach_adapter,
@ -217,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client
reference for later use. reference for later use.
Device Detection (Standard driver model)
----------------------------------------
Sometimes you do not know in advance which I2C devices are connected to
a given I2C bus. This is for example the case of hardware monitoring
devices on a PC's SMBus. In that case, you may want to let your driver
detect supported devices automatically. This is how the legacy model
was working, and is now available as an extension to the standard
driver model (so that we can finally get rid of the legacy model.)
You simply have to define a detect callback which will attempt to
identify supported devices (returning 0 for supported ones and -ENODEV
for unsupported ones), a list of addresses to probe, and a device type
(or class) so that only I2C buses which may have that type of device
connected (and not otherwise enumerated) will be probed. The i2c
core will then call you back as needed and will instantiate a device
for you for every successful detection.
Note that this mechanism is purely optional and not suitable for all
devices. You need some reliable way to identify the supported devices
(typically using device-specific, dedicated identification registers),
otherwise misdetections are likely to occur and things can get wrong
quickly.
Device Deletion (Standard driver model) Device Deletion (Standard driver model)
--------------------------------------- ---------------------------------------
@ -569,7 +598,6 @@ SMBus communication
in terms of it. Never use this function directly! in terms of it. Never use this function directly!
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte(struct i2c_client * client); extern s32 i2c_smbus_read_byte(struct i2c_client * client);
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value); extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@ -578,30 +606,31 @@ SMBus communication
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_word_data(struct i2c_client * client, extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
u8 command, u16 value); u8 command, u16 value);
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
u8 command, u8 *values);
extern s32 i2c_smbus_write_block_data(struct i2c_client * client, extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
u8 command, u8 length, u8 command, u8 length,
u8 *values); u8 *values);
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
u8 command, u8 length, u8 *values); u8 command, u8 length, u8 *values);
These ones were removed in Linux 2.6.10 because they had no users, but could
be added back later if needed:
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
u8 command, u8 *values);
extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
u8 command, u8 length, u8 command, u8 length,
u8 *values); u8 *values);
These ones were removed from i2c-core because they had no users, but could
be added back later if needed:
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_process_call(struct i2c_client * client, extern s32 i2c_smbus_process_call(struct i2c_client * client,
u8 command, u16 value); u8 command, u16 value);
extern s32 i2c_smbus_block_process_call(struct i2c_client *client, extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
u8 command, u8 length, u8 command, u8 length,
u8 *values) u8 *values)
All these transactions return -1 on failure. The 'write' transactions All these transactions return a negative errno value on failure. The 'write'
return 0 on success; the 'read' transactions return the read value, except transactions return 0 on success; the 'read' transactions return the read
for read_block, which returns the number of values read. The block buffers value, except for block transactions, which return the number of values
need not be longer than 32 bytes. read. The block buffers need not be longer than 32 bytes.
You can read the file `smbus-protocol' for more information about the You can read the file `smbus-protocol' for more information about the
actual SMBus protocol. actual SMBus protocol.

View File

@ -1686,6 +1686,13 @@ L: linuxppc-embedded@ozlabs.org
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
FREESCALE I2C CPM DRIVER
P: Jochen Friedrich
M: jochen@scram.de
L: linuxppc-dev@ozlabs.org
L: i2c@lm-sensors.org
S: Maintained
FREESCALE SOC FS_ENET DRIVER FREESCALE SOC FS_ENET DRIVER
P: Pantelis Antoniou P: Pantelis Antoniou
M: pantelis.antoniou@gmail.com M: pantelis.antoniou@gmail.com

View File

@ -1,3 +1,4 @@
obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o
obj-$(CONFIG_I2C_BOARDINFO) += swarm-i2c.o
obj-$(CONFIG_KGDB) += dbg_io.o obj-$(CONFIG_KGDB) += dbg_io.o

View File

@ -0,0 +1,37 @@
/*
* arch/mips/sibyte/swarm/swarm-i2c.c
*
* Broadcom BCM91250A (SWARM), etc. I2C platform setup.
*
* Copyright (c) 2008 Maciej W. Rozycki
*
* 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.
*/
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
static struct i2c_board_info swarm_i2c_info1[] __initdata = {
{
I2C_BOARD_INFO("m41t81", 0x68),
},
};
static int __init swarm_i2c_init(void)
{
int err;
err = i2c_register_board_info(1, swarm_i2c_info1,
ARRAY_SIZE(swarm_i2c_info1));
if (err < 0)
printk(KERN_ERR
"swarm-i2c: cannot register board I2C devices\n");
return err;
}
arch_initcall(swarm_i2c_init);

View File

@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries) unsigned char addr, int retries)
{ {
struct i2c_algo_bit_data *adap = i2c_adap->algo_data; struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
int i, ret = -1; int i, ret = 0;
for (i = 0; i <= retries; i++) { for (i = 0; i <= retries; i++) {
ret = i2c_outb(i2c_adap, addr); ret = i2c_outb(i2c_adap, addr);
@ -508,7 +508,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
addr ^= 1; addr ^= 1;
ret = try_address(i2c_adap, addr, retries); ret = try_address(i2c_adap, addr, retries);
if ((ret != 1) && !nak_ok) if ((ret != 1) && !nak_ok)
return -EREMOTEIO; return -ENXIO;
} }
return 0; return 0;

View File

@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
} }
if (state != 0xf8) { if (state != 0xf8) {
dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state); dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
return -EIO; return -EAGAIN;
} }
DEB1("{{{ XFER %d messages\n", num); DEB1("{{{ XFER %d messages\n", num);

View File

@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
set_pcf(adap, 1, I2C_PCF_STOP); set_pcf(adap, 1, I2C_PCF_STOP);
} }
static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
{
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
*status));
/* Cleanup from LAB -- reset and enable ESO.
* This resets the PCF8584; since we've lost the bus, no
* further attempts should be made by callers to clean up
* (no i2c_stop() etc.)
*/
set_pcf(adap, 1, I2C_PCF_PIN);
set_pcf(adap, 1, I2C_PCF_ESO);
/* We pause for a time period sufficient for any running
* I2C transaction to complete -- the arbitration logic won't
* work properly until the next START is seen.
* It is assumed the bus driver or client has set a proper value.
*
* REVISIT: should probably use msleep instead of mdelay if we
* know we can sleep.
*/
if (adap->lab_mdelay)
mdelay(adap->lab_mdelay);
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
get_pcf(adap, 1)));
}
static int wait_for_bb(struct i2c_algo_pcf_data *adap) { static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
int timeout = DEF_TIMEOUT; int timeout = DEF_TIMEOUT;
@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
*status = get_pcf(adap, 1); *status = get_pcf(adap, 1);
} }
if (*status & I2C_PCF_LAB) { if (*status & I2C_PCF_LAB) {
DEB2(printk(KERN_INFO handle_lab(adap, status);
"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
*status));
/* Cleanup from LAB-- reset and enable ESO.
* This resets the PCF8584; since we've lost the bus, no
* further attempts should be made by callers to clean up
* (no i2c_stop() etc.)
*/
set_pcf(adap, 1, I2C_PCF_PIN);
set_pcf(adap, 1, I2C_PCF_ESO);
/* TODO: we should pause for a time period sufficient for any
* running I2C transaction to complete-- the arbitration
* logic won't work properly until the next START is seen.
*/
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
get_pcf(adap,1)));
return(-EINTR); return(-EINTR);
} }
#endif #endif

View File

@ -4,6 +4,9 @@
menu "I2C Hardware Bus support" menu "I2C Hardware Bus support"
comment "PC SMBus host controller drivers"
depends on PCI
config I2C_ALI1535 config I2C_ALI1535
tristate "ALI 1535" tristate "ALI 1535"
depends on PCI depends on PCI
@ -73,6 +76,186 @@ config I2C_AMD8111
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-amd8111. will be called i2c-amd8111.
config I2C_I801
tristate "Intel 82801 (ICH)"
depends on PCI
help
If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following
versions of the chipset are supported:
82801AA
82801AB
82801BA
82801CA/CAM
82801DB
82801EB/ER (ICH5/ICH5R)
6300ESB
ICH6
ICH7
ESB2
ICH8
ICH9
Tolapai
ICH10
This driver can also be built as a module. If so, the module
will be called i2c-i801.
config I2C_ISCH
tristate "Intel SCH SMBus 1.0"
depends on PCI
help
Say Y here if you want to use SMBus controller on the Intel SCH
based systems.
This driver can also be built as a module. If so, the module
will be called i2c-isch.
config I2C_PIIX4
tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
depends on PCI
help
If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following
versions of the chipset are supported (note that Serverworks is part
of Broadcom):
Intel PIIX4
Intel 440MX
ATI IXP200
ATI IXP300
ATI IXP400
ATI SB600
ATI SB700
ATI SB800
Serverworks OSB4
Serverworks CSB5
Serverworks CSB6
Serverworks HT-1000
SMSC Victory66
This driver can also be built as a module. If so, the module
will be called i2c-piix4.
config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4"
depends on PCI
help
If you say yes to this option, support will be included for the Nvidia
nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
This driver can also be built as a module. If so, the module
will be called i2c-nforce2.
config I2C_NFORCE2_S4985
tristate "SMBus multiplexing on the Tyan S4985"
depends on I2C_NFORCE2 && EXPERIMENTAL
help
Enabling this option will add specific SMBus support for the Tyan
S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed
over 4 different channels, where the various memory module EEPROMs
live. Saying yes here will give you access to these in addition
to the trunk.
This driver can also be built as a module. If so, the module
will be called i2c-nforce2-s4985.
config I2C_SIS5595
tristate "SiS 5595"
depends on PCI
help
If you say yes to this option, support will be included for the
SiS5595 SMBus (a subset of I2C) interface.
This driver can also be built as a module. If so, the module
will be called i2c-sis5595.
config I2C_SIS630
tristate "SiS 630/730"
depends on PCI
help
If you say yes to this option, support will be included for the
SiS630 and SiS730 SMBus (a subset of I2C) interface.
This driver can also be built as a module. If so, the module
will be called i2c-sis630.
config I2C_SIS96X
tristate "SiS 96x"
depends on PCI
help
If you say yes to this option, support will be included for the SiS
96x SMBus (a subset of I2C) interfaces. Specifically, the following
chipsets are supported:
645/961
645DX/961
645DX/962
648/961
650/961
735
745
This driver can also be built as a module. If so, the module
will be called i2c-sis96x.
config I2C_VIA
tristate "VIA VT82C586B"
depends on PCI && EXPERIMENTAL
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the VIA
82C586B I2C interface
This driver can also be built as a module. If so, the module
will be called i2c-via.
config I2C_VIAPRO
tristate "VIA VT82C596/82C686/82xx and CX700"
depends on PCI
help
If you say yes to this option, support will be included for the VIA
VT82C596 and later SMBus interface. Specifically, the following
chipsets are supported:
VT82C596A/B
VT82C686A/B
VT8231
VT8233/A
VT8235
VT8237R/A/S
VT8251
CX700
This driver can also be built as a module. If so, the module
will be called i2c-viapro.
comment "Mac SMBus host controller drivers"
depends on PPC_CHRP || PPC_PMAC
config I2C_HYDRA
tristate "CHRP Apple Hydra Mac I/O I2C interface"
depends on PCI && PPC_CHRP && EXPERIMENTAL
select I2C_ALGOBIT
help
This supports the use of the I2C interface in the Apple Hydra Mac
I/O chip on some CHRP machines (e.g. the LongTrail). Say Y if you
have such a machine.
This support is also available as a module. If so, the module
will be called i2c-hydra.
config I2C_POWERMAC
tristate "Powermac I2C interface"
depends on PPC_PMAC
default y
help
This exposes the various PowerMac i2c interfaces to the linux i2c
layer and to userland. It is used by various drivers on the PowerMac
platform, and should generally be enabled.
This support is also available as a module. If so, the module
will be called i2c-powermac.
comment "I2C system bus drivers (mostly embedded / system-on-chip)"
config I2C_AT91 config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)" tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on ARCH_AT91 && EXPERIMENTAL && BROKEN depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
@ -101,10 +284,9 @@ config I2C_AU1550
config I2C_BLACKFIN_TWI config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support" tristate "Blackfin TWI I2C support"
depends on BLACKFIN depends on BLACKFIN
depends on !BF561 && !BF531 && !BF532 && !BF533
help help
This is the TWI I2C device driver for Blackfin BF522, BF525, This is the I2C bus driver for Blackfin on-chip TWI interface.
BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
please don't use this driver.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-bfin-twi. will be called i2c-bfin-twi.
@ -117,6 +299,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
help help
The unit of the TWI clock is kHz. The unit of the TWI clock is kHz.
config I2C_CPM
tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
depends on (CPM1 || CPM2) && OF_I2C
help
This supports the use of the I2C interface on Freescale
processors with CPM1 or CPM2.
This driver can also be built as a module. If so, the module
will be called i2c-cpm.
config I2C_DAVINCI config I2C_DAVINCI
tristate "DaVinci I2C driver" tristate "DaVinci I2C driver"
depends on ARCH_DAVINCI depends on ARCH_DAVINCI
@ -130,17 +322,6 @@ config I2C_DAVINCI
devices such as DaVinci NIC. devices such as DaVinci NIC.
For details please see http://www.ti.com/davinci For details please see http://www.ti.com/davinci
config I2C_ELEKTOR
tristate "Elektor ISA card"
depends on ISA && BROKEN_ON_SMP
select I2C_ALGOPCF
help
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
such an adapter.
This support is also available as a module. If so, the module
will be called i2c-elektor.
config I2C_GPIO config I2C_GPIO
tristate "GPIO-based bitbanging I2C" tristate "GPIO-based bitbanging I2C"
depends on GENERIC_GPIO depends on GENERIC_GPIO
@ -149,104 +330,6 @@ config I2C_GPIO
This is a very simple bitbanging I2C driver utilizing the This is a very simple bitbanging I2C driver utilizing the
arch-neutral GPIO API to control the SCL and SDA lines. arch-neutral GPIO API to control the SCL and SDA lines.
config I2C_HYDRA
tristate "CHRP Apple Hydra Mac I/O I2C interface"
depends on PCI && PPC_CHRP && EXPERIMENTAL
select I2C_ALGOBIT
help
This supports the use of the I2C interface in the Apple Hydra Mac
I/O chip on some CHRP machines (e.g. the LongTrail). Say Y if you
have such a machine.
This support is also available as a module. If so, the module
will be called i2c-hydra.
config I2C_I801
tristate "Intel 82801 (ICH)"
depends on PCI
help
If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following
versions of the chipset are supported:
82801AA
82801AB
82801BA
82801CA/CAM
82801DB
82801EB/ER (ICH5/ICH5R)
6300ESB
ICH6
ICH7
ESB2
ICH8
ICH9
Tolapai
ICH10
This driver can also be built as a module. If so, the module
will be called i2c-i801.
config I2C_I810
tristate "Intel 810/815 (DEPRECATED)"
default n
depends on PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the Intel
810/815 family of mainboard I2C interfaces. Specifically, the
following versions of the chipset are supported:
i810AA
i810AB
i810E
i815
i845G
This driver is deprecated in favor of the i810fb and intelfb drivers.
This driver can also be built as a module. If so, the module
will be called i2c-i810.
config I2C_PXA
tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
depends on EXPERIMENTAL && ARCH_PXA
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
will be called i2c-pxa.
config I2C_PXA_SLAVE
bool "Intel PXA2XX I2C Slave comms support"
depends on I2C_PXA
help
Support I2C slave mode communications on the PXA I2C bus. This
is necessary for systems where the PXA may be a target on the
I2C bus.
config I2C_PIIX4
tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
depends on PCI
help
If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following
versions of the chipset are supported (note that Serverworks is part
of Broadcom):
Intel PIIX4
Intel 440MX
ATI IXP200
ATI IXP300
ATI IXP400
ATI SB600
ATI SB700
ATI SB800
Serverworks OSB4
Serverworks CSB5
Serverworks CSB6
Serverworks HT-1000
SMSC Victory66
This driver can also be built as a module. If so, the module
will be called i2c-piix4.
config I2C_IBM_IIC config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface" tristate "IBM PPC 4xx on-chip I2C interface"
depends on 4xx depends on 4xx
@ -281,18 +364,6 @@ config I2C_IXP2000
This driver is deprecated and will be dropped soon. Use i2c-gpio This driver is deprecated and will be dropped soon. Use i2c-gpio
instead. instead.
config I2C_POWERMAC
tristate "Powermac I2C interface"
depends on PPC_PMAC
default y
help
This exposes the various PowerMac i2c interfaces to the linux i2c
layer and to userland. It is used by various drivers on the PowerMac
platform, and should generally be enabled.
This support is also available as a module. If so, the module
will be called i2c-powermac.
config I2C_MPC config I2C_MPC
tristate "MPC107/824x/85xx/52xx/86xx" tristate "MPC107/824x/85xx/52xx/86xx"
depends on PPC32 depends on PPC32
@ -305,15 +376,15 @@ config I2C_MPC
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-mpc. will be called i2c-mpc.
config I2C_NFORCE2 config I2C_MV64XXX
tristate "Nvidia nForce2, nForce3 and nForce4" tristate "Marvell mv64xxx I2C Controller"
depends on PCI depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
help help
If you say yes to this option, support will be included for the Nvidia If you say yes to this option, support will be included for the
nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. built-in I2C interface on the Marvell 64xxx line of host bridges.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-nforce2. will be called i2c-mv64xxx.
config I2C_OCORES config I2C_OCORES
tristate "OpenCores I2C Controller" tristate "OpenCores I2C Controller"
@ -336,6 +407,89 @@ config I2C_OMAP
Like OMAP1510/1610/1710/5912 and OMAP242x. Like OMAP1510/1610/1710/5912 and OMAP242x.
For details see http://www.ti.com/omap. For details see http://www.ti.com/omap.
config I2C_PASEMI
tristate "PA Semi SMBus interface"
depends on PPC_PASEMI && PCI
help
Supports the PA Semi PWRficient on-chip SMBus interfaces.
config I2C_PNX
tristate "I2C bus support for Philips PNX targets"
depends on ARCH_PNX4008
help
This driver supports the Philips IP3204 I2C IP block master and/or
slave controller
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
config I2C_PXA
tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
depends on EXPERIMENTAL && ARCH_PXA
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
will be called i2c-pxa.
config I2C_PXA_SLAVE
bool "Intel PXA2XX I2C Slave comms support"
depends on I2C_PXA
help
Support I2C slave mode communications on the PXA I2C bus. This
is necessary for systems where the PXA may be a target on the
I2C bus.
config I2C_S3C2410
tristate "S3C2410 I2C Driver"
depends on ARCH_S3C2410
help
Say Y here to include support for I2C controller in the
Samsung S3C2410 based System-on-Chip devices.
config I2C_SH7760
tristate "Renesas SH7760 I2C Controller"
depends on CPU_SUBTYPE_SH7760
help
This driver supports the 2 I2C interfaces on the Renesas SH7760.
This driver can also be built as a module. If so, the module
will be called i2c-sh7760.
config I2C_SH_MOBILE
tristate "SuperH Mobile I2C Controller"
depends on SUPERH
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Renesas SH-Mobile processor.
This driver can also be built as a module. If so, the module
will be called i2c-sh_mobile.
config I2C_SIMTEC
tristate "Simtec Generic I2C interface"
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for
the Simtec Generic I2C interface. This driver is for the
simple I2C bus used on newer Simtec products for general
I2C, such as DDC on the Simtec BBD2016A.
This driver can also be built as a module. If so, the module
will be called i2c-simtec.
config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support"
depends on ARCH_VERSATILE || ARCH_REALVIEW
select I2C_ALGOBIT
help
Say yes if you want to support the I2C serial bus on ARMs Versatile
range of platforms.
This driver can also be built as a module. If so, the module
will be called i2c-versatile.
comment "External I2C/SMBus adapter drivers"
config I2C_PARPORT config I2C_PARPORT
tristate "Parallel port adapter" tristate "Parallel port adapter"
depends on PARPORT depends on PARPORT
@ -383,50 +537,106 @@ config I2C_PARPORT_LIGHT
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-parport-light. will be called i2c-parport-light.
config I2C_PASEMI config I2C_TAOS_EVM
tristate "PA Semi SMBus interface" tristate "TAOS evaluation module"
depends on PPC_PASEMI && PCI depends on EXPERIMENTAL
help select SERIO
Supports the PA Semi PWRficient on-chip SMBus interfaces. select SERIO_SERPORT
config I2C_PROSAVAGE
tristate "S3/VIA (Pro)Savage (DEPRECATED)"
default n default n
depends on PCI
select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the This supports TAOS evaluation modules on serial port. In order to
I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8 use this driver, you will need the inputattach tool, which is part
graphics processors. of the input-utils package.
chipsets supported:
S3/VIA KM266/VT8375 aka ProSavage8
S3/VIA KM133/VT8365 aka Savage4
This driver is deprecated in favor of the savagefb driver. If unsure, say N.
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-prosavage. will be called i2c-taos-evm.
config I2C_S3C2410 config I2C_TINY_USB
tristate "S3C2410 I2C Driver" tristate "Tiny-USB adapter"
depends on ARCH_S3C2410 depends on USB
help help
Say Y here to include support for I2C controller in the If you say yes to this option, support will be included for the
Samsung S3C2410 based System-on-Chip devices. i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
config I2C_SAVAGE4 This driver can also be built as a module. If so, the module
tristate "S3 Savage 4 (DEPRECATED)" will be called i2c-tiny-usb.
default n
comment "Graphics adapter I2C/DDC channel drivers"
depends on PCI
config I2C_VOODOO3
tristate "Voodoo 3"
depends on PCI depends on PCI
select I2C_ALGOBIT select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
S3 Savage 4 I2C interface. Voodoo 3 I2C interface.
This driver is deprecated in favor of the savagefb driver.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-savage4. will be called i2c-voodoo3.
comment "Other I2C/SMBus bus drivers"
config I2C_ACORN
tristate "Acorn IOC/IOMD I2C bus support"
depends on ARCH_ACORN
default y
select I2C_ALGOBIT
help
Say yes if you want to support the I2C bus on Acorn platforms.
If you don't know, say Y.
config I2C_ELEKTOR
tristate "Elektor ISA card"
depends on ISA && BROKEN_ON_SMP
select I2C_ALGOPCF
help
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
such an adapter.
This support is also available as a module. If so, the module
will be called i2c-elektor.
config I2C_PCA_ISA
tristate "PCA9564 on an ISA bus"
depends on ISA
select I2C_ALGOPCA
default n
help
This driver supports ISA boards using the Philips PCA9564
parallel bus to I2C bus controller.
This driver can also be built as a module. If so, the module
will be called i2c-pca-isa.
This device is almost undetectable and using this driver on a
system which doesn't have this device will result in long
delays when I2C/SMBus chip drivers are loaded (e.g. at boot
time). If unsure, say N.
config I2C_PCA_PLATFORM
tristate "PCA9564 as platform device"
select I2C_ALGOPCA
default n
help
This driver supports a memory mapped Philips PCA9564
parallel bus to I2C bus controller.
This driver can also be built as a module. If so, the module
will be called i2c-pca-platform.
config I2C_PMCMSP
tristate "PMC MSP I2C TWI Controller"
depends on PMC_MSP
help
This driver supports the PMC TWI controller on MSP devices.
This driver can also be built as module. If so, the module
will be called i2c-pmcmsp.
config I2C_SIBYTE config I2C_SIBYTE
tristate "SiByte SMBus interface" tristate "SiByte SMBus interface"
@ -434,17 +644,18 @@ config I2C_SIBYTE
help help
Supports the SiByte SOC on-chip I2C interfaces (2 channels). Supports the SiByte SOC on-chip I2C interfaces (2 channels).
config I2C_SIMTEC config I2C_STUB
tristate "Simtec Generic I2C interface" tristate "I2C/SMBus Test Stub"
select I2C_ALGOBIT depends on EXPERIMENTAL && m
default 'n'
help help
If you say yes to this option, support will be included for This module may be useful to developers of SMBus client drivers,
the Simtec Generic I2C interface. This driver is for the especially for certain kinds of sensor chips.
simple I2C bus used on newer Simtec products for general
I2C, such as DDC on the Simtec BBD2016A.
This driver can also be built as a module. If so, the module If you do build this module, be sure to read the notes and warnings
will be called i2c-simtec. in <file:Documentation/i2c/i2c-stub>.
If you don't know what to do here, definitely say N.
config SCx200_I2C config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)" tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
@ -489,220 +700,4 @@ config SCx200_ACB
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called scx200_acb. will be called scx200_acb.
config I2C_SIS5595
tristate "SiS 5595"
depends on PCI
help
If you say yes to this option, support will be included for the
SiS5595 SMBus (a subset of I2C) interface.
This driver can also be built as a module. If so, the module
will be called i2c-sis5595.
config I2C_SIS630
tristate "SiS 630/730"
depends on PCI
help
If you say yes to this option, support will be included for the
SiS630 and SiS730 SMBus (a subset of I2C) interface.
This driver can also be built as a module. If so, the module
will be called i2c-sis630.
config I2C_SIS96X
tristate "SiS 96x"
depends on PCI
help
If you say yes to this option, support will be included for the SiS
96x SMBus (a subset of I2C) interfaces. Specifically, the following
chipsets are supported:
645/961
645DX/961
645DX/962
648/961
650/961
735
745
This driver can also be built as a module. If so, the module
will be called i2c-sis96x.
config I2C_TAOS_EVM
tristate "TAOS evaluation module"
depends on EXPERIMENTAL
select SERIO
select SERIO_SERPORT
default n
help
This supports TAOS evaluation modules on serial port. In order to
use this driver, you will need the inputattach tool, which is part
of the input-utils package.
If unsure, say N.
This support is also available as a module. If so, the module
will be called i2c-taos-evm.
config I2C_STUB
tristate "I2C/SMBus Test Stub"
depends on EXPERIMENTAL && m
default 'n'
help
This module may be useful to developers of SMBus client drivers,
especially for certain kinds of sensor chips.
If you do build this module, be sure to read the notes and warnings
in <file:Documentation/i2c/i2c-stub>.
If you don't know what to do here, definitely say N.
config I2C_TINY_USB
tristate "I2C-Tiny-USB"
depends on USB
help
If you say yes to this option, support will be included for the
i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
This driver can also be built as a module. If so, the module
will be called i2c-tiny-usb.
config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support"
depends on ARCH_VERSATILE || ARCH_REALVIEW
select I2C_ALGOBIT
help
Say yes if you want to support the I2C serial bus on ARMs Versatile
range of platforms.
This driver can also be built as a module. If so, the module
will be called i2c-versatile.
config I2C_ACORN
tristate "Acorn IOC/IOMD I2C bus support"
depends on ARCH_ACORN
default y
select I2C_ALGOBIT
help
Say yes if you want to support the I2C bus on Acorn platforms.
If you don't know, say Y.
config I2C_VIA
tristate "VIA 82C586B"
depends on PCI && EXPERIMENTAL
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the VIA
82C586B I2C interface
This driver can also be built as a module. If so, the module
will be called i2c-via.
config I2C_VIAPRO
tristate "VIA VT82C596/82C686/82xx and CX700"
depends on PCI
help
If you say yes to this option, support will be included for the VIA
VT82C596 and later SMBus interface. Specifically, the following
chipsets are supported:
VT82C596A/B
VT82C686A/B
VT8231
VT8233/A
VT8235
VT8237R/A/S
VT8251
CX700
This driver can also be built as a module. If so, the module
will be called i2c-viapro.
config I2C_VOODOO3
tristate "Voodoo 3"
depends on PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the
Voodoo 3 I2C interface.
This driver can also be built as a module. If so, the module
will be called i2c-voodoo3.
config I2C_PCA_ISA
tristate "PCA9564 on an ISA bus"
depends on ISA
select I2C_ALGOPCA
default n
help
This driver supports ISA boards using the Philips PCA9564
parallel bus to I2C bus controller.
This driver can also be built as a module. If so, the module
will be called i2c-pca-isa.
This device is almost undetectable and using this driver on a
system which doesn't have this device will result in long
delays when I2C/SMBus chip drivers are loaded (e.g. at boot
time). If unsure, say N.
config I2C_PCA_PLATFORM
tristate "PCA9564 as platform device"
select I2C_ALGOPCA
default n
help
This driver supports a memory mapped Philips PCA9564
parallel bus to I2C bus controller.
This driver can also be built as a module. If so, the module
will be called i2c-pca-platform.
config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller"
depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Marvell 64xxx line of host bridges.
This driver can also be built as a module. If so, the module
will be called i2c-mv64xxx.
config I2C_PNX
tristate "I2C bus support for Philips PNX targets"
depends on ARCH_PNX4008
help
This driver supports the Philips IP3204 I2C IP block master and/or
slave controller
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
config I2C_PMCMSP
tristate "PMC MSP I2C TWI Controller"
depends on PMC_MSP
help
This driver supports the PMC TWI controller on MSP devices.
This driver can also be built as module. If so, the module
will be called i2c-pmcmsp.
config I2C_SH7760
tristate "Renesas SH7760 I2C Controller"
depends on CPU_SUBTYPE_SH7760
help
This driver supports the 2 I2C interfaces on the Renesas SH7760.
This driver can also be built as a module. If so, the module
will be called i2c-sh7760.
config I2C_SH_MOBILE
tristate "SuperH Mobile I2C Controller"
depends on SUPERH
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Renesas SH-Mobile processor.
This driver can also be built as a module. If so, the module
will be called i2c-sh_mobile.
endmenu endmenu

View File

@ -2,57 +2,68 @@
# Makefile for the i2c bus drivers. # Makefile for the i2c bus drivers.
# #
# PC SMBus host controller drivers
obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o
obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o
obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_I810) += i2c-i810.o obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.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_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIA) += i2c-via.o
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
# Mac SMBus host controller drivers
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
# Embebbed system I2C/SMBus host controller drivers
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
# Graphics adapter I2C/DDC channel drivers
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
# Other I2C/SMBus bus drivers
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o

View File

@ -1,6 +1,4 @@
/* /*
i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Philip Edelbrock <phil@netroedge.com>,
Mark D. Studebaker <mdsxyz123@yahoo.com>, Mark D. Studebaker <mdsxyz123@yahoo.com>,
@ -61,6 +59,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
@ -159,6 +158,11 @@ static int ali1535_setup(struct pci_dev *dev)
goto exit; goto exit;
} }
retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE,
ali1535_driver.name);
if (retval)
goto exit;
if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
ali1535_driver.name)) { ali1535_driver.name)) {
dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n", dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
@ -259,7 +263,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
dev_err(&adap->dev, dev_err(&adap->dev,
"SMBus reset failed! (0x%02x) - controller or " "SMBus reset failed! (0x%02x) - controller or "
"device on bus is probably hung\n", temp); "device on bus is probably hung\n", temp);
return -1; return -EBUSY;
} }
} else { } else {
/* check and clear done bit */ /* check and clear done bit */
@ -281,12 +285,12 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n"); dev_err(&adap->dev, "SMBus Timeout!\n");
} }
if (temp & ALI1535_STS_FAIL) { if (temp & ALI1535_STS_FAIL) {
result = -1; result = -EIO;
dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
} }
@ -295,7 +299,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
* do a printk. This means that bus collisions go unreported. * do a printk. This means that bus collisions go unreported.
*/ */
if (temp & ALI1535_STS_BUSERR) { if (temp & ALI1535_STS_BUSERR) {
result = -1; result = -ENXIO;
dev_dbg(&adap->dev, dev_dbg(&adap->dev,
"Error: no response or bus collision ADD=%02x\n", "Error: no response or bus collision ADD=%02x\n",
inb_p(SMBHSTADD)); inb_p(SMBHSTADD));
@ -303,13 +307,13 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* haven't ever seen this */ /* haven't ever seen this */
if (temp & ALI1535_STS_DEV) { if (temp & ALI1535_STS_DEV) {
result = -1; result = -EIO;
dev_err(&adap->dev, "Error: device error\n"); dev_err(&adap->dev, "Error: device error\n");
} }
/* check to see if the "command complete" indication is set */ /* check to see if the "command complete" indication is set */
if (!(temp & ALI1535_STS_DONE)) { if (!(temp & ALI1535_STS_DONE)) {
result = -1; result = -ETIMEDOUT;
dev_err(&adap->dev, "Error: command never completed\n"); dev_err(&adap->dev, "Error: command never completed\n");
} }
@ -332,7 +336,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data) int size, union i2c_smbus_data *data)
@ -357,10 +361,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
outb_p(0xFF, SMBHSTSTS); outb_p(0xFF, SMBHSTSTS);
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
result = -1;
goto EXIT;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD); SMBHSTADD);
@ -418,14 +418,16 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
outb_p(data->block[i], SMBBLKDAT); outb_p(data->block[i], SMBBLKDAT);
} }
break; break;
} default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
if (ali1535_transaction(adap)) { result = -EOPNOTSUPP;
/* Error in transaction */
result = -1;
goto EXIT; goto EXIT;
} }
result = ali1535_transaction(adap);
if (result)
goto EXIT;
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) {
result = 0; result = 0;
goto EXIT; goto EXIT;
@ -475,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali1535_adapter = { static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI1535, .id = I2C_HW_SMBUS_ALI1535,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };

View File

@ -21,6 +21,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#define ALI1563_MAX_TIMEOUT 500 #define ALI1563_MAX_TIMEOUT 500
#define ALI1563_SMBBA 0x80 #define ALI1563_SMBBA 0x80
@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
{ {
u32 data; u32 data;
int timeout; int timeout;
int status = -EIO;
dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, " dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
/* Issue 'kill' to host controller */ /* Issue 'kill' to host controller */
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
data = inb_p(SMB_HST_STS); data = inb_p(SMB_HST_STS);
status = -ETIMEDOUT;
} }
/* device error - no response, ignore the autodetection case */ /* device error - no response, ignore the autodetection case */
if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) { if (data & HST_STS_DEVERR) {
dev_err(&a->dev, "Device error!\n"); if (size != HST_CNTL2_QUICK)
dev_err(&a->dev, "Device error!\n");
status = -ENXIO;
} }
/* bus collision */ /* bus collision */
if (data & HST_STS_BUSERR) { if (data & HST_STS_BUSERR) {
dev_err(&a->dev, "Bus collision!\n"); dev_err(&a->dev, "Bus collision!\n");
@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
outb_p(0x0,SMB_HST_CNTL2); outb_p(0x0,SMB_HST_CNTL2);
} }
return -1; return status;
} }
static int ali1563_block_start(struct i2c_adapter * a) static int ali1563_block_start(struct i2c_adapter * a)
{ {
u32 data; u32 data;
int timeout; int timeout;
int status = -EIO;
dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, " dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD)) if (timeout && !(data & HST_STS_BAD))
return 0; return 0;
if (timeout == 0)
status = -ETIMEDOUT;
if (data & HST_STS_DEVERR)
status = -ENXIO;
dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n", dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
timeout ? "Timeout " : "", timeout ? "" : "Timeout ",
data & HST_STS_FAIL ? "Transaction Failed " : "", data & HST_STS_FAIL ? "Transaction Failed " : "",
data & HST_STS_BUSERR ? "No response or Bus Collision " : "", data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
data & HST_STS_DEVERR ? "Device Error " : "", data & HST_STS_DEVERR ? "Device Error " : "",
!(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
return -1; return status;
} }
static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
/* Map the size to what the chip understands */ /* Map the size to what the chip understands */
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
error = -EINVAL;
break;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
size = HST_CNTL2_QUICK; size = HST_CNTL2_QUICK;
break; break;
@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
size = HST_CNTL2_BLOCK; size = HST_CNTL2_BLOCK;
break; break;
default:
dev_warn(&a->dev, "Unsupported transaction %d\n", size);
error = -EOPNOTSUPP;
goto Done;
} }
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
} }
} }
if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE,
ali1563_pci_driver.name))
goto Err;
if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE, if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
ali1563_pci_driver.name)) { ali1563_pci_driver.name)) {
dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n", dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = {
static struct i2c_adapter ali1563_adapter = { static struct i2c_adapter ali1563_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI1563, .id = I2C_HW_SMBUS_ALI1563,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ali1563_algorithm, .algo = &ali1563_algorithm,
}; };

View File

@ -1,6 +1,4 @@
/* /*
ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com> and Philip Edelbrock <phil@netroedge.com> and
Mark D. Studebaker <mdsxyz123@yahoo.com> Mark D. Studebaker <mdsxyz123@yahoo.com>
@ -68,6 +66,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* ALI15X3 SMBus address offsets */ /* ALI15X3 SMBus address offsets */
@ -166,6 +165,10 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
if(force_addr) if(force_addr)
ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
ali15x3_driver.name))
return -EBUSY;
if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
ali15x3_driver.name)) { ali15x3_driver.name)) {
dev_err(&ALI15X3_dev->dev, dev_err(&ALI15X3_dev->dev,
@ -282,7 +285,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - " dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "
"controller or device on bus is probably hung\n", "controller or device on bus is probably hung\n",
temp); temp);
return -1; return -EBUSY;
} }
} else { } else {
/* check and clear done bit */ /* check and clear done bit */
@ -304,12 +307,12 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n"); dev_err(&adap->dev, "SMBus Timeout!\n");
} }
if (temp & ALI15X3_STS_TERM) { if (temp & ALI15X3_STS_TERM) {
result = -1; result = -EIO;
dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
} }
@ -320,7 +323,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
This means that bus collisions go unreported. This means that bus collisions go unreported.
*/ */
if (temp & ALI15X3_STS_COLL) { if (temp & ALI15X3_STS_COLL) {
result = -1; result = -ENXIO;
dev_dbg(&adap->dev, dev_dbg(&adap->dev,
"Error: no response or bus collision ADD=%02x\n", "Error: no response or bus collision ADD=%02x\n",
inb_p(SMBHSTADD)); inb_p(SMBHSTADD));
@ -328,7 +331,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
/* haven't ever seen this */ /* haven't ever seen this */
if (temp & ALI15X3_STS_DEV) { if (temp & ALI15X3_STS_DEV) {
result = -1; result = -EIO;
dev_err(&adap->dev, "Error: device error\n"); dev_err(&adap->dev, "Error: device error\n");
} }
dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
@ -338,7 +341,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data) int size, union i2c_smbus_data * data)
@ -362,9 +365,6 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
} }
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD); SMBHSTADD);
@ -417,12 +417,16 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
} }
size = ALI15X3_BLOCK_DATA; size = ALI15X3_BLOCK_DATA;
break; break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
} }
outb_p(size, SMBHSTCNT); /* output command */ outb_p(size, SMBHSTCNT); /* output command */
if (ali15x3_transaction(adap)) /* Error in transaction */ temp = ali15x3_transaction(adap);
return -1; if (temp)
return temp;
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
return 0; return 0;
@ -470,7 +474,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali15x3_adapter = { static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI15X3, .id = I2C_HW_SMBUS_ALI15X3,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };

View File

@ -58,7 +58,7 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
/* We exclude the multiplexed addresses */ /* We exclude the multiplexed addresses */
if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
|| addr == 0x18) || addr == 0x18)
return -1; return -ENXIO;
mutex_lock(&amd756_lock); mutex_lock(&amd756_lock);
@ -86,7 +86,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
/* We exclude the non-multiplexed addresses */ /* We exclude the non-multiplexed addresses */
if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
return -1; return -ENXIO;
mutex_lock(&amd756_lock); mutex_lock(&amd756_lock);

View File

@ -1,7 +1,4 @@
/* /*
amd756.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
Shamelessly ripped from i2c-piix4.c: Shamelessly ripped from i2c-piix4.c:
@ -45,6 +42,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* AMD756 SMBus address offsets */ /* AMD756 SMBus address offsets */
@ -151,17 +149,17 @@ static int amd756_transaction(struct i2c_adapter *adap)
} }
if (temp & GS_PRERR_STS) { if (temp & GS_PRERR_STS) {
result = -1; result = -ENXIO;
dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
} }
if (temp & GS_COL_STS) { if (temp & GS_COL_STS) {
result = -1; result = -EIO;
dev_warn(&adap->dev, "SMBus collision!\n"); dev_warn(&adap->dev, "SMBus collision!\n");
} }
if (temp & GS_TO_STS) { if (temp & GS_TO_STS) {
result = -1; result = -ETIMEDOUT;
dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); dev_dbg(&adap->dev, "SMBus protocol timeout!\n");
} }
@ -189,22 +187,18 @@ static int amd756_transaction(struct i2c_adapter *adap)
outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
msleep(100); msleep(100);
outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
return -1; return -EIO;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 amd756_access(struct i2c_adapter * adap, u16 addr, static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
{ {
int i, len; int i, len;
int status;
/** TODO: Should I supporte the 10-bit transfers? */
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
/* TODO: Well... It is supported, I'm just not sure what to do here... */
return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMB_HOST_ADDRESS); SMB_HOST_ADDRESS);
@ -251,13 +245,17 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
} }
size = AMD756_BLOCK_DATA; size = AMD756_BLOCK_DATA;
break; break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
} }
/* How about enabling interrupts... */ /* How about enabling interrupts... */
outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
if (amd756_transaction(adap)) /* Error in transaction */ status = amd756_transaction(adap);
return -1; if (status)
return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
return 0; return 0;
@ -301,7 +299,7 @@ static const struct i2c_algorithm smbus_algorithm = {
struct i2c_adapter amd756_smbus = { struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_AMD756, .id = I2C_HW_SMBUS_AMD756,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
@ -368,6 +366,11 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
amd756_ioport += SMB_ADDR_OFFSET; amd756_ioport += SMB_ADDR_OFFSET;
} }
error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
amd756_driver.name);
if (error)
return error;
if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
amd756_ioport); amd756_ioport);

View File

@ -16,6 +16,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -77,7 +78,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
if (!timeout) { if (!timeout) {
dev_warn(&smbus->dev->dev, dev_warn(&smbus->dev->dev,
"Timeout while waiting for IBF to clear\n"); "Timeout while waiting for IBF to clear\n");
return -1; return -ETIMEDOUT;
} }
return 0; return 0;
@ -93,7 +94,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
if (!timeout) { if (!timeout) {
dev_warn(&smbus->dev->dev, dev_warn(&smbus->dev->dev,
"Timeout while waiting for OBF to set\n"); "Timeout while waiting for OBF to set\n");
return -1; return -ETIMEDOUT;
} }
return 0; return 0;
@ -102,16 +103,21 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
unsigned char *data) unsigned char *data)
{ {
if (amd_ec_wait_write(smbus)) int status;
return -1;
status = amd_ec_wait_write(smbus);
if (status)
return status;
outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD); outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
if (amd_ec_wait_write(smbus)) status = amd_ec_wait_write(smbus);
return -1; if (status)
return status;
outb(address, smbus->base + AMD_EC_DATA); outb(address, smbus->base + AMD_EC_DATA);
if (amd_ec_wait_read(smbus)) status = amd_ec_wait_read(smbus);
return -1; if (status)
return status;
*data = inb(smbus->base + AMD_EC_DATA); *data = inb(smbus->base + AMD_EC_DATA);
return 0; return 0;
@ -120,16 +126,21 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
unsigned char data) unsigned char data)
{ {
if (amd_ec_wait_write(smbus)) int status;
return -1;
status = amd_ec_wait_write(smbus);
if (status)
return status;
outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD); outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
if (amd_ec_wait_write(smbus)) status = amd_ec_wait_write(smbus);
return -1; if (status)
return status;
outb(address, smbus->base + AMD_EC_DATA); outb(address, smbus->base + AMD_EC_DATA);
if (amd_ec_wait_write(smbus)) status = amd_ec_wait_write(smbus);
return -1; if (status)
return status;
outb(data, smbus->base + AMD_EC_DATA); outb(data, smbus->base + AMD_EC_DATA);
return 0; return 0;
@ -267,12 +278,17 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
default: default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size); dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
} }
amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
/* FIXME this discards status from ec_read(); so temp[0] will
* hold stack garbage ... the rest of this routine will act
* nonsensically. Ignored ec_write() status might explain
* some such failures...
*/
amd_ec_read(smbus, AMD_SMB_STS, temp + 0); amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
if (~temp[0] & AMD_SMB_STS_DONE) { if (~temp[0] & AMD_SMB_STS_DONE) {
@ -286,7 +302,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
} }
if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
return -1; return -EIO;
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
return 0; return 0;
@ -359,6 +375,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
smbus->base = pci_resource_start(dev, 0); smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0); smbus->size = pci_resource_len(dev, 0);
error = acpi_check_resource_conflict(&dev->resource[0]);
if (error)
goto out_kfree;
if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
error = -EBUSY; error = -EBUSY;
goto out_kfree; goto out_kfree;
@ -368,7 +388,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus2 AMD8111 adapter at %04x", smbus->base); "SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_HW_SMBUS_AMD8111; smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;

View File

@ -269,9 +269,13 @@ static int
au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{ {
struct i2c_au1550_data *adap = i2c_adap->algo_data; struct i2c_au1550_data *adap = i2c_adap->algo_data;
volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
struct i2c_msg *p; struct i2c_msg *p;
int i, err = 0; int i, err = 0;
sp->psc_ctrl = PSC_CTRL_ENABLE;
au_sync();
for (i = 0; !err && i < num; i++) { for (i = 0; !err && i < num; i++) {
p = &msgs[i]; p = &msgs[i];
err = do_address(adap, p->addr, p->flags & I2C_M_RD, err = do_address(adap, p->addr, p->flags & I2C_M_RD,
@ -288,6 +292,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
*/ */
if (err == 0) if (err == 0)
err = num; err = num;
sp->psc_ctrl = PSC_CTRL_SUSPEND;
au_sync();
return err; return err;
} }
@ -302,53 +310,11 @@ static const struct i2c_algorithm au1550_algo = {
.functionality = au1550_func, .functionality = au1550_func,
}; };
/* static void i2c_au1550_setup(struct i2c_au1550_data *priv)
* registering functions to load algorithms at runtime
* Prior to calling us, the 50MHz clock frequency and routing
* must have been set up for the PSC indicated by the adapter.
*/
static int __devinit
i2c_au1550_probe(struct platform_device *pdev)
{ {
struct i2c_au1550_data *priv; volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
volatile psc_smb_t *sp;
struct resource *r;
u32 stat; u32 stat;
int ret;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
ret = -ENODEV;
goto out;
}
priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto out;
}
priv->ioarea = request_mem_region(r->start, r->end - r->start + 1,
pdev->name);
if (!priv->ioarea) {
ret = -EBUSY;
goto out_mem;
}
priv->psc_base = CKSEG1ADDR(r->start);
priv->xfer_timeout = 200;
priv->ack_timeout = 200;
priv->adap.id = I2C_HW_AU1550_PSC;
priv->adap.nr = pdev->id;
priv->adap.algo = &au1550_algo;
priv->adap.algo_data = priv;
priv->adap.dev.parent = &pdev->dev;
strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
/* Now, set up the PSC for SMBus PIO mode.
*/
sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_ctrl = PSC_CTRL_DISABLE; sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync(); au_sync();
sp->psc_sel = PSC_SEL_PS_SMBUSMODE; sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
@ -384,7 +350,66 @@ i2c_au1550_probe(struct platform_device *pdev)
do { do {
stat = sp->psc_smbstat; stat = sp->psc_smbstat;
au_sync(); au_sync();
} while ((stat & PSC_SMBSTAT_DR) == 0); } while ((stat & PSC_SMBSTAT_SR) == 0);
sp->psc_ctrl = PSC_CTRL_SUSPEND;
au_sync();
}
static void i2c_au1550_disable(struct i2c_au1550_data *priv)
{
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_smbcfg = 0;
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
}
/*
* registering functions to load algorithms at runtime
* Prior to calling us, the 50MHz clock frequency and routing
* must have been set up for the PSC indicated by the adapter.
*/
static int __devinit
i2c_au1550_probe(struct platform_device *pdev)
{
struct i2c_au1550_data *priv;
struct resource *r;
int ret;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
ret = -ENODEV;
goto out;
}
priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto out;
}
priv->ioarea = request_mem_region(r->start, r->end - r->start + 1,
pdev->name);
if (!priv->ioarea) {
ret = -EBUSY;
goto out_mem;
}
priv->psc_base = CKSEG1ADDR(r->start);
priv->xfer_timeout = 200;
priv->ack_timeout = 200;
priv->adap.id = I2C_HW_AU1550_PSC;
priv->adap.nr = pdev->id;
priv->adap.algo = &au1550_algo;
priv->adap.algo_data = priv;
priv->adap.dev.parent = &pdev->dev;
strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
/* Now, set up the PSC for SMBus PIO mode.
*/
i2c_au1550_setup(priv);
ret = i2c_add_numbered_adapter(&priv->adap); ret = i2c_add_numbered_adapter(&priv->adap);
if (ret == 0) { if (ret == 0) {
@ -392,10 +417,7 @@ i2c_au1550_probe(struct platform_device *pdev)
return 0; return 0;
} }
/* disable the PSC */ i2c_au1550_disable(priv);
sp->psc_smbcfg = 0;
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
release_resource(priv->ioarea); release_resource(priv->ioarea);
kfree(priv->ioarea); kfree(priv->ioarea);
@ -409,27 +431,24 @@ static int __devexit
i2c_au1550_remove(struct platform_device *pdev) i2c_au1550_remove(struct platform_device *pdev)
{ {
struct i2c_au1550_data *priv = platform_get_drvdata(pdev); struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
i2c_del_adapter(&priv->adap); i2c_del_adapter(&priv->adap);
sp->psc_smbcfg = 0; i2c_au1550_disable(priv);
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
release_resource(priv->ioarea); release_resource(priv->ioarea);
kfree(priv->ioarea); kfree(priv->ioarea);
kfree(priv); kfree(priv);
return 0; return 0;
} }
#ifdef CONFIG_PM
static int static int
i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state) i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
{ {
struct i2c_au1550_data *priv = platform_get_drvdata(pdev); struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_ctrl = PSC_CTRL_SUSPEND; i2c_au1550_disable(priv);
au_sync();
return 0; return 0;
} }
@ -437,14 +456,15 @@ static int
i2c_au1550_resume(struct platform_device *pdev) i2c_au1550_resume(struct platform_device *pdev)
{ {
struct i2c_au1550_data *priv = platform_get_drvdata(pdev); struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_ctrl = PSC_CTRL_ENABLE; i2c_au1550_setup(priv);
au_sync();
while (!(sp->psc_smbstat & PSC_SMBSTAT_SR))
au_sync();
return 0; return 0;
} }
#else
#define i2c_au1550_suspend NULL
#define i2c_au1550_resume NULL
#endif
static struct platform_driver au1xpsc_smbus_driver = { static struct platform_driver au1xpsc_smbus_driver = {
.driver = { .driver = {

View File

@ -0,0 +1,745 @@
/*
* Freescale CPM1/CPM2 I2C interface.
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
*
* moved into proper i2c interface;
* Brad Parker (brad@heeltoe.com)
*
* Parts from dbox2_i2c.c (cvs.tuxbox.org)
* (C) 2000-2001 Felix Domke (tmbinc@gmx.net), Gillem (htoa@gmx.net)
*
* (C) 2007 Montavista Software, Inc.
* Vitaly Bordug <vitb@kernel.crashing.org>
*
* Converted to of_platform_device. Renamed to i2c-cpm.c.
* (C) 2007,2008 Jochen Friedrich <jochen@scram.de>
*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/stddef.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/of_i2c.h>
#include <sysdev/fsl_soc.h>
#include <asm/cpm.h>
/* Try to define this if you have an older CPU (earlier than rev D4) */
/* However, better use a GPIO based bitbang driver in this case :/ */
#undef I2C_CHIP_ERRATA
#define CPM_MAX_READ 513
#define CPM_MAXBD 4
#define I2C_EB (0x10) /* Big endian mode */
#define I2C_EB_CPM2 (0x30) /* Big endian mode, memory snoop */
#define DPRAM_BASE ((u8 __iomem __force *)cpm_muram_addr(0))
/* I2C parameter RAM. */
struct i2c_ram {
ushort rbase; /* Rx Buffer descriptor base address */
ushort tbase; /* Tx Buffer descriptor base address */
u_char rfcr; /* Rx function code */
u_char tfcr; /* Tx function code */
ushort mrblr; /* Max receive buffer length */
uint rstate; /* Internal */
uint rdp; /* Internal */
ushort rbptr; /* Rx Buffer descriptor pointer */
ushort rbc; /* Internal */
uint rxtmp; /* Internal */
uint tstate; /* Internal */
uint tdp; /* Internal */
ushort tbptr; /* Tx Buffer descriptor pointer */
ushort tbc; /* Internal */
uint txtmp; /* Internal */
char res1[4]; /* Reserved */
ushort rpbase; /* Relocation pointer */
char res2[2]; /* Reserved */
};
#define I2COM_START 0x80
#define I2COM_MASTER 0x01
#define I2CER_TXE 0x10
#define I2CER_BUSY 0x04
#define I2CER_TXB 0x02
#define I2CER_RXB 0x01
#define I2MOD_EN 0x01
/* I2C Registers */
struct i2c_reg {
u8 i2mod;
u8 res1[3];
u8 i2add;
u8 res2[3];
u8 i2brg;
u8 res3[3];
u8 i2com;
u8 res4[3];
u8 i2cer;
u8 res5[3];
u8 i2cmr;
};
struct cpm_i2c {
char *base;
struct of_device *ofdev;
struct i2c_adapter adap;
uint dp_addr;
int version; /* CPM1=1, CPM2=2 */
int irq;
int cp_command;
int freq;
struct i2c_reg __iomem *i2c_reg;
struct i2c_ram __iomem *i2c_ram;
u16 i2c_addr;
wait_queue_head_t i2c_wait;
cbd_t __iomem *tbase;
cbd_t __iomem *rbase;
u_char *txbuf[CPM_MAXBD];
u_char *rxbuf[CPM_MAXBD];
u32 txdma[CPM_MAXBD];
u32 rxdma[CPM_MAXBD];
};
static irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id)
{
struct cpm_i2c *cpm;
struct i2c_reg __iomem *i2c_reg;
struct i2c_adapter *adap = dev_id;
int i;
cpm = i2c_get_adapdata(dev_id);
i2c_reg = cpm->i2c_reg;
/* Clear interrupt. */
i = in_8(&i2c_reg->i2cer);
out_8(&i2c_reg->i2cer, i);
dev_dbg(&adap->dev, "Interrupt: %x\n", i);
wake_up_interruptible(&cpm->i2c_wait);
return i ? IRQ_HANDLED : IRQ_NONE;
}
static void cpm_reset_i2c_params(struct cpm_i2c *cpm)
{
struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
/* Set up the I2C parameters in the parameter ram. */
out_be16(&i2c_ram->tbase, (u8 __iomem *)cpm->tbase - DPRAM_BASE);
out_be16(&i2c_ram->rbase, (u8 __iomem *)cpm->rbase - DPRAM_BASE);
if (cpm->version == 1) {
out_8(&i2c_ram->tfcr, I2C_EB);
out_8(&i2c_ram->rfcr, I2C_EB);
} else {
out_8(&i2c_ram->tfcr, I2C_EB_CPM2);
out_8(&i2c_ram->rfcr, I2C_EB_CPM2);
}
out_be16(&i2c_ram->mrblr, CPM_MAX_READ);
out_be32(&i2c_ram->rstate, 0);
out_be32(&i2c_ram->rdp, 0);
out_be16(&i2c_ram->rbptr, 0);
out_be16(&i2c_ram->rbc, 0);
out_be32(&i2c_ram->rxtmp, 0);
out_be32(&i2c_ram->tstate, 0);
out_be32(&i2c_ram->tdp, 0);
out_be16(&i2c_ram->tbptr, 0);
out_be16(&i2c_ram->tbc, 0);
out_be32(&i2c_ram->txtmp, 0);
}
static void cpm_i2c_force_close(struct i2c_adapter *adap)
{
struct cpm_i2c *cpm = i2c_get_adapdata(adap);
struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
dev_dbg(&adap->dev, "cpm_i2c_force_close()\n");
cpm_command(cpm->cp_command, CPM_CR_CLOSE_RX_BD);
out_8(&i2c_reg->i2cmr, 0x00); /* Disable all interrupts */
out_8(&i2c_reg->i2cer, 0xff);
}
static void cpm_i2c_parse_message(struct i2c_adapter *adap,
struct i2c_msg *pmsg, int num, int tx, int rx)
{
cbd_t __iomem *tbdf;
cbd_t __iomem *rbdf;
u_char addr;
u_char *tb;
u_char *rb;
struct cpm_i2c *cpm = i2c_get_adapdata(adap);
tbdf = cpm->tbase + tx;
rbdf = cpm->rbase + rx;
addr = pmsg->addr << 1;
if (pmsg->flags & I2C_M_RD)
addr |= 1;
tb = cpm->txbuf[tx];
rb = cpm->rxbuf[rx];
/* Align read buffer */
rb = (u_char *) (((ulong) rb + 1) & ~1);
tb[0] = addr; /* Device address byte w/rw flag */
out_be16(&tbdf->cbd_datlen, pmsg->len + 1);
out_be16(&tbdf->cbd_sc, 0);
if (!(pmsg->flags & I2C_M_NOSTART))
setbits16(&tbdf->cbd_sc, BD_I2C_START);
if (tx + 1 == num)
setbits16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP);
if (pmsg->flags & I2C_M_RD) {
/*
* 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).
*/
dev_dbg(&adap->dev, "cpm_i2c_read(abyte=0x%x)\n", addr);
out_be16(&rbdf->cbd_datlen, 0);
out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
if (rx + 1 == CPM_MAXBD)
setbits16(&rbdf->cbd_sc, BD_SC_WRAP);
eieio();
setbits16(&tbdf->cbd_sc, BD_SC_READY);
} else {
dev_dbg(&adap->dev, "cpm_i2c_write(abyte=0x%x)\n", addr);
memcpy(tb+1, pmsg->buf, pmsg->len);
eieio();
setbits16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_INTRPT);
}
}
static int cpm_i2c_check_message(struct i2c_adapter *adap,
struct i2c_msg *pmsg, int tx, int rx)
{
cbd_t __iomem *tbdf;
cbd_t __iomem *rbdf;
u_char *tb;
u_char *rb;
struct cpm_i2c *cpm = i2c_get_adapdata(adap);
tbdf = cpm->tbase + tx;
rbdf = cpm->rbase + rx;
tb = cpm->txbuf[tx];
rb = cpm->rxbuf[rx];
/* Align read buffer */
rb = (u_char *) (((uint) rb + 1) & ~1);
eieio();
if (pmsg->flags & I2C_M_RD) {
dev_dbg(&adap->dev, "tx sc 0x%04x, rx sc 0x%04x\n",
in_be16(&tbdf->cbd_sc), in_be16(&rbdf->cbd_sc));
if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) {
dev_dbg(&adap->dev, "I2C read; No ack\n");
return -ENXIO;
}
if (in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY) {
dev_err(&adap->dev,
"I2C read; complete but rbuf empty\n");
return -EREMOTEIO;
}
if (in_be16(&rbdf->cbd_sc) & BD_SC_OV) {
dev_err(&adap->dev, "I2C read; Overrun\n");
return -EREMOTEIO;
}
memcpy(pmsg->buf, rb, pmsg->len);
} else {
dev_dbg(&adap->dev, "tx sc %d 0x%04x\n", tx,
in_be16(&tbdf->cbd_sc));
if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) {
dev_dbg(&adap->dev, "I2C write; No ack\n");
return -ENXIO;
}
if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) {
dev_err(&adap->dev, "I2C write; Underrun\n");
return -EIO;
}
if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) {
dev_err(&adap->dev, "I2C write; Collision\n");
return -EIO;
}
}
return 0;
}
static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
struct cpm_i2c *cpm = i2c_get_adapdata(adap);
struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
struct i2c_msg *pmsg;
int ret, i;
int tptr;
int rptr;
cbd_t __iomem *tbdf;
cbd_t __iomem *rbdf;
if (num > CPM_MAXBD)
return -EINVAL;
/* Check if we have any oversized READ requests */
for (i = 0; i < num; i++) {
pmsg = &msgs[i];
if (pmsg->len >= CPM_MAX_READ)
return -EINVAL;
}
/* Reset to use first buffer */
out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
tbdf = cpm->tbase;
rbdf = cpm->rbase;
tptr = 0;
rptr = 0;
while (tptr < num) {
pmsg = &msgs[tptr];
dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr);
cpm_i2c_parse_message(adap, pmsg, num, tptr, rptr);
if (pmsg->flags & I2C_M_RD)
rptr++;
tptr++;
}
/* Start transfer now */
/* Enable RX/TX/Error interupts */
out_8(&i2c_reg->i2cmr, I2CER_TXE | I2CER_TXB | I2CER_RXB);
out_8(&i2c_reg->i2cer, 0xff); /* Clear interrupt status */
/* Chip bug, set enable here */
setbits8(&i2c_reg->i2mod, I2MOD_EN); /* Enable */
/* Begin transmission */
setbits8(&i2c_reg->i2com, I2COM_START);
tptr = 0;
rptr = 0;
while (tptr < num) {
/* Check for outstanding messages */
dev_dbg(&adap->dev, "test ready.\n");
pmsg = &msgs[tptr];
if (pmsg->flags & I2C_M_RD)
ret = wait_event_interruptible_timeout(cpm->i2c_wait,
!(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY),
1 * HZ);
else
ret = wait_event_interruptible_timeout(cpm->i2c_wait,
!(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY),
1 * HZ);
if (ret == 0) {
ret = -EREMOTEIO;
dev_err(&adap->dev, "I2C transfer: timeout\n");
goto out_err;
}
if (ret > 0) {
dev_dbg(&adap->dev, "ready.\n");
ret = cpm_i2c_check_message(adap, pmsg, tptr, rptr);
tptr++;
if (pmsg->flags & I2C_M_RD)
rptr++;
if (ret)
goto out_err;
}
}
#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);
clrbits8(&i2c_reg->i2mod, I2MOD_EN);
#endif
return (num);
out_err:
cpm_i2c_force_close(adap);
#ifdef I2C_CHIP_ERRATA
/*
* Chip errata, clear enable. This is not needed on rev D4 CPUs.
*/
clrbits8(&i2c_reg->i2mod, I2MOD_EN);
#endif
return ret;
}
static u32 cpm_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
}
/* -----exported algorithm data: ------------------------------------- */
static const struct i2c_algorithm cpm_i2c_algo = {
.master_xfer = cpm_i2c_xfer,
.functionality = cpm_i2c_func,
};
static const struct i2c_adapter cpm_ops = {
.owner = THIS_MODULE,
.name = "i2c-cpm",
.algo = &cpm_i2c_algo,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
};
static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)
{
struct of_device *ofdev = cpm->ofdev;
const u32 *data;
int len, ret, i;
void __iomem *i2c_base;
cbd_t __iomem *tbdf;
cbd_t __iomem *rbdf;
unsigned char brg;
dev_dbg(&cpm->ofdev->dev, "cpm_i2c_setup()\n");
init_waitqueue_head(&cpm->i2c_wait);
cpm->irq = of_irq_to_resource(ofdev->node, 0, NULL);
if (cpm->irq == NO_IRQ)
return -EINVAL;
/* Install interrupt handler. */
ret = request_irq(cpm->irq, cpm_i2c_interrupt, 0, "cpm_i2c",
&cpm->adap);
if (ret)
return ret;
/* I2C parameter RAM */
i2c_base = of_iomap(ofdev->node, 1);
if (i2c_base == NULL) {
ret = -EINVAL;
goto out_irq;
}
if (of_device_is_compatible(ofdev->node, "fsl,cpm1-i2c")) {
/* Check for and use a microcode relocation patch. */
cpm->i2c_ram = i2c_base;
cpm->i2c_addr = in_be16(&cpm->i2c_ram->rpbase);
/*
* Maybe should use cpm_muram_alloc instead of hardcoding
* this in micropatch.c
*/
if (cpm->i2c_addr) {
cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
iounmap(i2c_base);
}
cpm->version = 1;
} else if (of_device_is_compatible(ofdev->node, "fsl,cpm2-i2c")) {
cpm->i2c_addr = cpm_muram_alloc(sizeof(struct i2c_ram), 64);
cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
out_be16(i2c_base, cpm->i2c_addr);
iounmap(i2c_base);
cpm->version = 2;
} else {
iounmap(i2c_base);
ret = -EINVAL;
goto out_irq;
}
/* I2C control/status registers */
cpm->i2c_reg = of_iomap(ofdev->node, 0);
if (cpm->i2c_reg == NULL) {
ret = -EINVAL;
goto out_ram;
}
data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
if (!data || len != 4) {
ret = -EINVAL;
goto out_reg;
}
cpm->cp_command = *data;
data = of_get_property(ofdev->node, "linux,i2c-class", &len);
if (data && len == 4)
cpm->adap.class = *data;
data = of_get_property(ofdev->node, "clock-frequency", &len);
if (data && len == 4)
cpm->freq = *data;
else
cpm->freq = 60000; /* use 60kHz i2c clock by default */
/*
* Allocate space for CPM_MAXBD transmit and receive buffer
* descriptors in the DP ram.
*/
cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8);
if (!cpm->dp_addr) {
ret = -ENOMEM;
goto out_reg;
}
cpm->tbase = cpm_muram_addr(cpm->dp_addr);
cpm->rbase = cpm_muram_addr(cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD);
/* Allocate TX and RX buffers */
tbdf = cpm->tbase;
rbdf = cpm->rbase;
for (i = 0; i < CPM_MAXBD; i++) {
cpm->rxbuf[i] = dma_alloc_coherent(
NULL, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL);
if (!cpm->rxbuf[i]) {
ret = -ENOMEM;
goto out_muram;
}
out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1));
cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(
NULL, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL);
if (!cpm->txbuf[i]) {
ret = -ENOMEM;
goto out_muram;
}
out_be32(&tbdf[i].cbd_bufaddr, cpm->txdma[i]);
}
/* Initialize Tx/Rx parameters. */
cpm_reset_i2c_params(cpm);
dev_dbg(&cpm->ofdev->dev, "i2c_ram 0x%p, i2c_addr 0x%04x, freq %d\n",
cpm->i2c_ram, cpm->i2c_addr, cpm->freq);
dev_dbg(&cpm->ofdev->dev, "tbase 0x%04x, rbase 0x%04x\n",
(u8 __iomem *)cpm->tbase - DPRAM_BASE,
(u8 __iomem *)cpm->rbase - DPRAM_BASE);
cpm_command(cpm->cp_command, CPM_CR_INIT_TRX);
/*
* Select an invalid address. Just make sure we don't use loopback mode
*/
out_8(&cpm->i2c_reg->i2add, 0x7f << 1);
/*
* PDIV is set to 00 in i2mod, so brgclk/32 is used as input to the
* i2c baud rate generator. This is divided by 2 x (DIV + 3) to get
* the actual i2c bus frequency.
*/
brg = get_brgfreq() / (32 * 2 * cpm->freq) - 3;
out_8(&cpm->i2c_reg->i2brg, brg);
out_8(&cpm->i2c_reg->i2mod, 0x00);
out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); /* Master mode */
/* Disable interrupts. */
out_8(&cpm->i2c_reg->i2cmr, 0);
out_8(&cpm->i2c_reg->i2cer, 0xff);
return 0;
out_muram:
for (i = 0; i < CPM_MAXBD; i++) {
if (cpm->rxbuf[i])
dma_free_coherent(NULL, CPM_MAX_READ + 1,
cpm->rxbuf[i], cpm->rxdma[i]);
if (cpm->txbuf[i])
dma_free_coherent(NULL, CPM_MAX_READ + 1,
cpm->txbuf[i], cpm->txdma[i]);
}
cpm_muram_free(cpm->dp_addr);
out_reg:
iounmap(cpm->i2c_reg);
out_ram:
if ((cpm->version == 1) && (!cpm->i2c_addr))
iounmap(cpm->i2c_ram);
if (cpm->version == 2)
cpm_muram_free(cpm->i2c_addr);
out_irq:
free_irq(cpm->irq, &cpm->adap);
return ret;
}
static void cpm_i2c_shutdown(struct cpm_i2c *cpm)
{
int i;
/* Shut down I2C. */
clrbits8(&cpm->i2c_reg->i2mod, I2MOD_EN);
/* Disable interrupts */
out_8(&cpm->i2c_reg->i2cmr, 0);
out_8(&cpm->i2c_reg->i2cer, 0xff);
free_irq(cpm->irq, &cpm->adap);
/* Free all memory */
for (i = 0; i < CPM_MAXBD; i++) {
dma_free_coherent(NULL, CPM_MAX_READ + 1,
cpm->rxbuf[i], cpm->rxdma[i]);
dma_free_coherent(NULL, CPM_MAX_READ + 1,
cpm->txbuf[i], cpm->txdma[i]);
}
cpm_muram_free(cpm->dp_addr);
iounmap(cpm->i2c_reg);
if ((cpm->version == 1) && (!cpm->i2c_addr))
iounmap(cpm->i2c_ram);
if (cpm->version == 2)
cpm_muram_free(cpm->i2c_addr);
}
static int __devinit cpm_i2c_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
int result, len;
struct cpm_i2c *cpm;
const u32 *data;
cpm = kzalloc(sizeof(struct cpm_i2c), GFP_KERNEL);
if (!cpm)
return -ENOMEM;
cpm->ofdev = ofdev;
dev_set_drvdata(&ofdev->dev, cpm);
cpm->adap = cpm_ops;
i2c_set_adapdata(&cpm->adap, cpm);
cpm->adap.dev.parent = &ofdev->dev;
result = cpm_i2c_setup(cpm);
if (result) {
dev_err(&ofdev->dev, "Unable to init hardware\n");
goto out_free;
}
/* register new adapter to i2c module... */
data = of_get_property(ofdev->node, "linux,i2c-index", &len);
if (data && len == 4) {
cpm->adap.nr = *data;
result = i2c_add_numbered_adapter(&cpm->adap);
} else
result = i2c_add_adapter(&cpm->adap);
if (result < 0) {
dev_err(&ofdev->dev, "Unable to register with I2C\n");
goto out_shut;
}
dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
cpm->adap.name);
/*
* register OF I2C devices
*/
of_register_i2c_devices(&cpm->adap, ofdev->node);
return 0;
out_shut:
cpm_i2c_shutdown(cpm);
out_free:
dev_set_drvdata(&ofdev->dev, NULL);
kfree(cpm);
return result;
}
static int __devexit cpm_i2c_remove(struct of_device *ofdev)
{
struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev);
i2c_del_adapter(&cpm->adap);
cpm_i2c_shutdown(cpm);
dev_set_drvdata(&ofdev->dev, NULL);
kfree(cpm);
return 0;
}
static const struct of_device_id cpm_i2c_match[] = {
{
.compatible = "fsl,cpm1-i2c",
},
{
.compatible = "fsl,cpm2-i2c",
},
{},
};
MODULE_DEVICE_TABLE(of, cpm_i2c_match);
static struct of_platform_driver cpm_i2c_driver = {
.match_table = cpm_i2c_match,
.probe = cpm_i2c_probe,
.remove = __devexit_p(cpm_i2c_remove),
.driver = {
.name = "fsl-i2c-cpm",
.owner = THIS_MODULE,
}
};
static int __init cpm_i2c_init(void)
{
return of_register_platform_driver(&cpm_i2c_driver);
}
static void __exit cpm_i2c_exit(void)
{
of_unregister_platform_driver(&cpm_i2c_driver);
}
module_init(cpm_i2c_init);
module_exit(cpm_i2c_exit);
MODULE_AUTHOR("Jochen Friedrich <jochen@scram.de>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards");
MODULE_LICENSE("GPL");

View File

@ -85,6 +85,7 @@
#define DAVINCI_I2C_MDR_MST (1 << 10) #define DAVINCI_I2C_MDR_MST (1 << 10)
#define DAVINCI_I2C_MDR_TRX (1 << 9) #define DAVINCI_I2C_MDR_TRX (1 << 9)
#define DAVINCI_I2C_MDR_XA (1 << 8) #define DAVINCI_I2C_MDR_XA (1 << 8)
#define DAVINCI_I2C_MDR_RM (1 << 7)
#define DAVINCI_I2C_MDR_IRS (1 << 5) #define DAVINCI_I2C_MDR_IRS (1 << 5)
#define DAVINCI_I2C_IMR_AAS (1 << 6) #define DAVINCI_I2C_IMR_AAS (1 << 6)
@ -112,6 +113,7 @@ struct davinci_i2c_dev {
u8 *buf; u8 *buf;
size_t buf_len; size_t buf_len;
int irq; int irq;
u8 terminate;
struct i2c_adapter adapter; struct i2c_adapter adapter;
}; };
@ -142,6 +144,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
u16 psc; u16 psc;
u32 clk; u32 clk;
u32 d;
u32 clkh; u32 clkh;
u32 clkl; u32 clkl;
u32 input_clock = clk_get_rate(dev->clk); u32 input_clock = clk_get_rate(dev->clk);
@ -171,23 +174,29 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
* if PSC > 1 , d = 5 * if PSC > 1 , d = 5
*/ */
psc = 26; /* To get 1MHz clock */ /* get minimum of 7 MHz clock, but max of 12 MHz */
psc = (input_clock / 7000000) - 1;
if ((input_clock / (psc + 1)) > 12000000)
psc++; /* better to run under spec than over */
d = (psc >= 2) ? 5 : 7 - psc;
clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - 10; clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1);
clkh = (50 * clk) / 100; clkh = clk >> 1;
clkl = clk - clkh; clkl = clk - clkh;
davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
dev_dbg(dev->dev, "CLK = %d\n", clk); dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
dev_dbg(dev->dev, "PSC = %d\n", dev_dbg(dev->dev, "PSC = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
dev_dbg(dev->dev, "CLKL = %d\n", dev_dbg(dev->dev, "CLKL = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
dev_dbg(dev->dev, "CLKH = %d\n", dev_dbg(dev->dev, "CLKH = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG));
dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n",
pdata->bus_freq, pdata->bus_delay);
/* Take the I2C module out of reset: */ /* Take the I2C module out of reset: */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
@ -233,7 +242,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
u32 flag; u32 flag;
u32 stat;
u16 w; u16 w;
int r; int r;
@ -254,12 +262,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len);
init_completion(&dev->cmd_complete); INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0; dev->cmd_err = 0;
/* Clear any pending interrupts by reading the IVR */
stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG);
/* Take I2C out of reset, configure it as master and set the /* Take I2C out of reset, configure it as master and set the
* start bit */ * start bit */
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
@ -280,20 +285,34 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1); MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1);
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
dev->terminate = 0;
/* write the data into mode register */ /* write the data into mode register */
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
DAVINCI_I2C_TIMEOUT); DAVINCI_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
if (r == 0) { if (r == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
i2c_davinci_init(dev); i2c_davinci_init(dev);
dev->buf_len = 0;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
if (dev->buf_len) {
/* This should be 0 if all bytes were transferred
* or dev->cmd_err denotes an error.
* A signal may have aborted the transfer.
*/
if (r >= 0) {
dev_err(dev->dev, "abnormal termination buf_len=%i\n",
dev->buf_len);
r = -EREMOTEIO;
}
dev->terminate = 1;
wmb();
dev->buf_len = 0;
}
if (r < 0)
return r;
/* no error */ /* no error */
if (likely(!dev->cmd_err)) if (likely(!dev->cmd_err))
@ -338,12 +357,11 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1))); ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1)));
dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
ret);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
return num; return num;
} }
@ -352,6 +370,27 @@ static u32 i2c_davinci_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
} }
static void terminate_read(struct davinci_i2c_dev *dev)
{
u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_NACK;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
/* Throw away data */
davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG);
if (!dev->terminate)
dev_err(dev->dev, "RDR IRQ while no data requested\n");
}
static void terminate_write(struct davinci_i2c_dev *dev)
{
u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
if (!dev->terminate)
dev_err(dev->dev, "TDR IRQ while no data to send\n");
}
/* /*
* Interrupt service routine. This gets called whenever an I2C interrupt * Interrupt service routine. This gets called whenever an I2C interrupt
* occurs. * occurs.
@ -372,12 +411,15 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
switch (stat) { switch (stat) {
case DAVINCI_I2C_IVR_AL: case DAVINCI_I2C_IVR_AL:
/* Arbitration lost, must retry */
dev->cmd_err |= DAVINCI_I2C_STR_AL; dev->cmd_err |= DAVINCI_I2C_STR_AL;
dev->buf_len = 0;
complete(&dev->cmd_complete); complete(&dev->cmd_complete);
break; break;
case DAVINCI_I2C_IVR_NACK: case DAVINCI_I2C_IVR_NACK:
dev->cmd_err |= DAVINCI_I2C_STR_NACK; dev->cmd_err |= DAVINCI_I2C_STR_NACK;
dev->buf_len = 0;
complete(&dev->cmd_complete); complete(&dev->cmd_complete);
break; break;
@ -399,9 +441,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
davinci_i2c_write_reg(dev, davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_REG,
DAVINCI_I2C_IMR_RRDY); DAVINCI_I2C_IMR_RRDY);
} else } else {
dev_err(dev->dev, "RDR IRQ while no " /* signal can terminate transfer */
"data requested\n"); terminate_read(dev);
}
break; break;
case DAVINCI_I2C_IVR_XRDY: case DAVINCI_I2C_IVR_XRDY:
@ -418,9 +461,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
davinci_i2c_write_reg(dev, davinci_i2c_write_reg(dev,
DAVINCI_I2C_IMR_REG, DAVINCI_I2C_IMR_REG,
w); w);
} else } else {
dev_err(dev->dev, "TDR IRQ while no data to " /* signal can terminate transfer */
"send\n"); terminate_write(dev);
}
break; break;
case DAVINCI_I2C_IVR_SCD: case DAVINCI_I2C_IVR_SCD:
@ -475,6 +519,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
goto err_release_region; goto err_release_region;
} }
init_completion(&dev->cmd_complete);
dev->dev = get_device(&pdev->dev); dev->dev = get_device(&pdev->dev);
dev->irq = irq->start; dev->irq = irq->start;
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);

View File

@ -196,13 +196,11 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
.getown = pcf_isa_getown, .getown = pcf_isa_getown,
.getclock = pcf_isa_getclock, .getclock = pcf_isa_getclock,
.waitforpin = pcf_isa_waitforpin, .waitforpin = pcf_isa_waitforpin,
.udelay = 10,
.timeout = 100,
}; };
static struct i2c_adapter pcf_isa_ops = { static struct i2c_adapter pcf_isa_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.id = I2C_HW_P_ELEK, .id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data, .algo_data = &pcf_isa_data,
.name = "i2c-elektor", .name = "i2c-elektor",

View File

@ -140,7 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data; adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev; adap->dev.parent = &pdev->dev;
/* /*

View File

@ -1,7 +1,4 @@
/* /*
i2c-hydra.c - Part of lm_sensors, Linux kernel modules
for hardware monitoring
i2c Support for the Apple `Hydra' Mac I/O i2c Support for the Apple `Hydra' Mac I/O
Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org> Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org>

View File

@ -1,10 +1,8 @@
/* /*
i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
<mdsxyz123@yahoo.com> <mdsxyz123@yahoo.com>
Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -64,6 +62,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* I801 SMBus address offsets */ /* I801 SMBus address offsets */
@ -121,6 +120,10 @@
#define SMBHSTSTS_INTR 0x02 #define SMBHSTSTS_INTR 0x02
#define SMBHSTSTS_HOST_BUSY 0x01 #define SMBHSTSTS_HOST_BUSY 0x01
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
SMBHSTSTS_INTR)
static unsigned long i801_smba; static unsigned long i801_smba;
static unsigned char i801_original_hstcfg; static unsigned char i801_original_hstcfg;
static struct pci_driver i801_driver; static struct pci_driver i801_driver;
@ -132,31 +135,96 @@ static struct pci_dev *I801_dev;
#define FEATURE_I2C_BLOCK_READ (1 << 3) #define FEATURE_I2C_BLOCK_READ (1 << 3)
static unsigned int i801_features; static unsigned int i801_features;
static int i801_transaction(int xact) /* Make sure the SMBus host is ready to start transmitting.
Return 0 if it is, -EBUSY if it is not. */
static int i801_check_pre(void)
{ {
int temp; int status;
int result = 0;
int timeout = 0;
dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, " status = inb_p(SMBHSTSTS);
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), if (status & SMBHSTSTS_HOST_BUSY) {
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n");
inb_p(SMBHSTDAT1)); return -EBUSY;
}
/* Make sure the SMBus host is ready to start transmitting */ status &= STATUS_FLAGS;
/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ if (status) {
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n",
dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n", status);
temp); outb_p(status, SMBHSTSTS);
outb_p(temp, SMBHSTSTS); status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { if (status) {
dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp); dev_err(&I801_dev->dev,
return -1; "Failed clearing status flags (%02x)\n",
} else { status);
dev_dbg(&I801_dev->dev, "Successful!\n"); return -EBUSY;
} }
} }
return 0;
}
/* Convert the status register to an error code, and clear it. */
static int i801_check_post(int status, int timeout)
{
int result = 0;
/* If the SMBus is still busy, we give up */
if (timeout) {
dev_err(&I801_dev->dev, "Transaction timeout\n");
/* try to stop the current command */
dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
msleep(1);
outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
/* Check if it worked */
status = inb_p(SMBHSTSTS);
if ((status & SMBHSTSTS_HOST_BUSY) ||
!(status & SMBHSTSTS_FAILED))
dev_err(&I801_dev->dev,
"Failed terminating the transaction\n");
outb_p(STATUS_FLAGS, SMBHSTSTS);
return -ETIMEDOUT;
}
if (status & SMBHSTSTS_FAILED) {
result = -EIO;
dev_err(&I801_dev->dev, "Transaction failed\n");
}
if (status & SMBHSTSTS_DEV_ERR) {
result = -ENXIO;
dev_dbg(&I801_dev->dev, "No response\n");
}
if (status & SMBHSTSTS_BUS_ERR) {
result = -EAGAIN;
dev_dbg(&I801_dev->dev, "Lost arbitration\n");
}
if (result) {
/* Clear error flags */
outb_p(status & STATUS_FLAGS, SMBHSTSTS);
status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
if (status) {
dev_warn(&I801_dev->dev, "Failed clearing status "
"flags at end of transaction (%02x)\n",
status);
}
}
return result;
}
static int i801_transaction(int xact)
{
int status;
int result;
int timeout = 0;
result = i801_check_pre();
if (result < 0)
return result;
/* the current contents of SMBHSTCNT can be overwritten, since PEC, /* the current contents of SMBHSTCNT can be overwritten, since PEC,
* INTREN, SMBSCMD are passed in xact */ * INTREN, SMBSCMD are passed in xact */
outb_p(xact | I801_START, SMBHSTCNT); outb_p(xact | I801_START, SMBHSTCNT);
@ -164,73 +232,40 @@ static int i801_transaction(int xact)
/* We will always wait for a fraction of a second! */ /* We will always wait for a fraction of a second! */
do { do {
msleep(1); msleep(1);
temp = inb_p(SMBHSTSTS); status = inb_p(SMBHSTSTS);
} while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ result = i801_check_post(status, timeout >= MAX_TIMEOUT);
if (timeout >= MAX_TIMEOUT) { if (result < 0)
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); return result;
result = -1;
/* try to stop the current command */
dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
msleep(1);
outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
}
if (temp & SMBHSTSTS_FAILED) { outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
result = -1; return 0;
dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
}
if (temp & SMBHSTSTS_BUS_ERR) {
result = -1;
dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
"until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
}
if (temp & SMBHSTSTS_DEV_ERR) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
outb_p(inb(SMBHSTSTS), SMBHSTSTS);
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
"(%02x)\n", temp);
}
dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTDAT1));
return result;
} }
/* wait for INTR bit as advised by Intel */ /* wait for INTR bit as advised by Intel */
static void i801_wait_hwpec(void) static void i801_wait_hwpec(void)
{ {
int timeout = 0; int timeout = 0;
int temp; int status;
do { do {
msleep(1); msleep(1);
temp = inb_p(SMBHSTSTS); status = inb_p(SMBHSTSTS);
} while ((!(temp & SMBHSTSTS_INTR)) } while ((!(status & SMBHSTSTS_INTR))
&& (timeout++ < MAX_TIMEOUT)); && (timeout++ < MAX_TIMEOUT));
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
} }
outb_p(temp, SMBHSTSTS); outb_p(status, SMBHSTSTS);
} }
static int i801_block_transaction_by_block(union i2c_smbus_data *data, static int i801_block_transaction_by_block(union i2c_smbus_data *data,
char read_write, int hwpec) char read_write, int hwpec)
{ {
int i, len; int i, len;
int status;
inb_p(SMBHSTCNT); /* reset the data buffer index */ inb_p(SMBHSTCNT); /* reset the data buffer index */
@ -242,14 +277,15 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
outb_p(data->block[i+1], SMBBLKDAT); outb_p(data->block[i+1], SMBBLKDAT);
} }
if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
I801_PEC_EN * hwpec)) I801_PEC_EN * hwpec);
return -1; if (status)
return status;
if (read_write == I2C_SMBUS_READ) { if (read_write == I2C_SMBUS_READ) {
len = inb_p(SMBHSTDAT0); len = inb_p(SMBHSTDAT0);
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
return -1; return -EPROTO;
data->block[0] = len; data->block[0] = len;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
@ -264,10 +300,13 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
{ {
int i, len; int i, len;
int smbcmd; int smbcmd;
int temp; int status;
int result = 0; int result;
int timeout; int timeout;
unsigned char errmask;
result = i801_check_pre();
if (result < 0)
return result;
len = data->block[0]; len = data->block[0];
@ -291,36 +330,6 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
} }
outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
/* Make sure the SMBus host is ready to start transmitting */
temp = inb_p(SMBHSTSTS);
if (i == 1) {
/* Erroneous conditions before transaction:
* Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
errmask = 0x9f;
} else {
/* Erroneous conditions during transaction:
* Failed, Bus_Err, Dev_Err, Intr */
errmask = 0x1e;
}
if (temp & errmask) {
dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
"Resetting...\n", temp);
outb_p(temp, SMBHSTSTS);
if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
dev_err(&I801_dev->dev,
"Reset failed! (%02x)\n", temp);
return -1;
}
if (i != 1)
/* if die in middle of block transaction, fail */
return -1;
}
if (i == 1) if (i == 1)
outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
@ -328,41 +337,28 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
timeout = 0; timeout = 0;
do { do {
msleep(1); msleep(1);
temp = inb_p(SMBHSTSTS); status = inb_p(SMBHSTSTS);
} }
while ((!(temp & SMBHSTSTS_BYTE_DONE)) while ((!(status & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_TIMEOUT)); && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ result = i801_check_post(status, timeout >= MAX_TIMEOUT);
if (timeout >= MAX_TIMEOUT) { if (result < 0)
/* try to stop the current command */ return result;
dev_dbg(&I801_dev->dev, "Terminating the current "
"operation\n");
outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
msleep(1);
outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
SMBHSTCNT);
result = -1;
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
}
if (temp & SMBHSTSTS_FAILED) {
result = -1;
dev_dbg(&I801_dev->dev,
"Error: Failed bus transaction\n");
} else if (temp & SMBHSTSTS_BUS_ERR) {
result = -1;
dev_err(&I801_dev->dev, "Bus collision!\n");
} else if (temp & SMBHSTSTS_DEV_ERR) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
if (i == 1 && read_write == I2C_SMBUS_READ if (i == 1 && read_write == I2C_SMBUS_READ
&& command != I2C_SMBUS_I2C_BLOCK_DATA) { && command != I2C_SMBUS_I2C_BLOCK_DATA) {
len = inb_p(SMBHSTDAT0); len = inb_p(SMBHSTDAT0);
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
return -1; dev_err(&I801_dev->dev,
"Illegal SMBus block read size %d\n",
len);
/* Recover */
while (inb_p(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY)
outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS);
outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
return -EPROTO;
}
data->block[0] = len; data->block[0] = len;
} }
@ -371,30 +367,19 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
data->block[i] = inb_p(SMBBLKDAT); data->block[i] = inb_p(SMBBLKDAT);
if (read_write == I2C_SMBUS_WRITE && i+1 <= len) if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
outb_p(data->block[i+1], SMBBLKDAT); outb_p(data->block[i+1], SMBBLKDAT);
if ((temp & 0x9e) != 0x00)
outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { /* signals SMBBLKDAT ready */
dev_dbg(&I801_dev->dev, outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS);
"Bad status (%02x) at end of transaction\n",
temp);
}
dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
if (result < 0)
return result;
} }
return result;
return 0;
} }
static int i801_set_block_buffer_mode(void) static int i801_set_block_buffer_mode(void)
{ {
outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL); outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0) if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
return -1; return -EIO;
return 0; return 0;
} }
@ -414,7 +399,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
} else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) { } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
dev_err(&I801_dev->dev, dev_err(&I801_dev->dev,
"I2C block read is unsupported!\n"); "I2C block read is unsupported!\n");
return -1; return -EOPNOTSUPP;
} }
} }
@ -449,7 +434,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 i801_access(struct i2c_adapter * adap, u16 addr, static s32 i801_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data) int size, union i2c_smbus_data * data)
@ -511,10 +496,9 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
outb_p(command, SMBHSTCMD); outb_p(command, SMBHSTCMD);
block = 1; block = 1;
break; break;
case I2C_SMBUS_PROC_CALL:
default: default:
dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
} }
if (hwpec) /* enable/disable hardware PEC */ if (hwpec) /* enable/disable hardware PEC */
@ -537,7 +521,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
if(block) if(block)
return ret; return ret;
if(ret) if(ret)
return -1; return ret;
if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
return 0; return 0;
@ -572,7 +556,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter i801_adapter = { static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_I801, .id = I2C_HW_SMBUS_I801,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
@ -639,6 +623,10 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
goto exit; goto exit;
} }
err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
if (err)
goto exit;
err = pci_request_region(dev, SMBBAR, i801_driver.name); err = pci_request_region(dev, SMBBAR, i801_driver.name);
if (err) { if (err) {
dev_err(&dev->dev, "Failed to request SMBus region " dev_err(&dev->dev, "Failed to request SMBus region "

View File

@ -1,260 +0,0 @@
/*
i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999, 2000 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
Ralph Metzler <rjkm@thp.uni-koeln.de>, and
Mark D. Studebaker <mdsxyz123@yahoo.com>
Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
Simon 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.
*/
/*
This interfaces to the I810/I815 to provide access to
the DDC Bus and the I2C Bus.
SUPPORTED DEVICES PCI ID
i810AA 7121
i810AB 7123
i810E 7125
i815 1132
i845G 2562
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/io.h>
/* GPIO register locations */
#define I810_IOCONTROL_OFFSET 0x5000
#define I810_HVSYNC 0x00 /* not used */
#define I810_GPIOA 0x10
#define I810_GPIOB 0x14
/* bit locations in the registers */
#define SCL_DIR_MASK 0x0001
#define SCL_DIR 0x0002
#define SCL_VAL_MASK 0x0004
#define SCL_VAL_OUT 0x0008
#define SCL_VAL_IN 0x0010
#define SDA_DIR_MASK 0x0100
#define SDA_DIR 0x0200
#define SDA_VAL_MASK 0x0400
#define SDA_VAL_OUT 0x0800
#define SDA_VAL_IN 0x1000
/* initialization states */
#define INIT1 0x1
#define INIT2 0x2
#define INIT3 0x4
/* delays */
#define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2)
static void __iomem *ioaddr;
/* The i810 GPIO registers have individual masks for each bit
so we never have to read before writing. Nice. */
static void bit_i810i2c_setscl(void *data, int val)
{
writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
ioaddr + I810_GPIOB);
readl(ioaddr + I810_GPIOB); /* flush posted write */
}
static void bit_i810i2c_setsda(void *data, int val)
{
writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
ioaddr + I810_GPIOB);
readl(ioaddr + I810_GPIOB); /* flush posted write */
}
/* The GPIO pins are open drain, so the pins could always remain outputs.
However, some chip versions don't latch the inputs unless they
are set as inputs.
We rely on the i2c-algo-bit routines to set the pins high before
reading the input from other chips. Following guidance in the 815
prog. ref. guide, we do a "dummy write" of 0 to the register before
reading which forces the input value to be latched. We presume this
applies to the 810 as well; shouldn't hurt anyway. This is necessary to get
i2c_algo_bit bit_test=1 to pass. */
static int bit_i810i2c_getscl(void *data)
{
writel(SCL_DIR_MASK, ioaddr + I810_GPIOB);
writel(0, ioaddr + I810_GPIOB);
return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN));
}
static int bit_i810i2c_getsda(void *data)
{
writel(SDA_DIR_MASK, ioaddr + I810_GPIOB);
writel(0, ioaddr + I810_GPIOB);
return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN));
}
static void bit_i810ddc_setscl(void *data, int val)
{
writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
ioaddr + I810_GPIOA);
readl(ioaddr + I810_GPIOA); /* flush posted write */
}
static void bit_i810ddc_setsda(void *data, int val)
{
writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
ioaddr + I810_GPIOA);
readl(ioaddr + I810_GPIOA); /* flush posted write */
}
static int bit_i810ddc_getscl(void *data)
{
writel(SCL_DIR_MASK, ioaddr + I810_GPIOA);
writel(0, ioaddr + I810_GPIOA);
return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN));
}
static int bit_i810ddc_getsda(void *data)
{
writel(SDA_DIR_MASK, ioaddr + I810_GPIOA);
writel(0, ioaddr + I810_GPIOA);
return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN));
}
static int config_i810(struct pci_dev *dev)
{
unsigned long cadr;
/* map I810 memory */
cadr = dev->resource[1].start;
cadr += I810_IOCONTROL_OFFSET;
cadr &= PCI_BASE_ADDRESS_MEM_MASK;
ioaddr = ioremap_nocache(cadr, 0x1000);
if (ioaddr) {
bit_i810i2c_setscl(NULL, 1);
bit_i810i2c_setsda(NULL, 1);
bit_i810ddc_setscl(NULL, 1);
bit_i810ddc_setsda(NULL, 1);
return 0;
}
return -ENODEV;
}
static struct i2c_algo_bit_data i810_i2c_bit_data = {
.setsda = bit_i810i2c_setsda,
.setscl = bit_i810i2c_setscl,
.getsda = bit_i810i2c_getsda,
.getscl = bit_i810i2c_getscl,
.udelay = CYCLE_DELAY,
.timeout = TIMEOUT,
};
static struct i2c_adapter i810_i2c_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_B_I810,
.name = "I810/I815 I2C Adapter",
.algo_data = &i810_i2c_bit_data,
};
static struct i2c_algo_bit_data i810_ddc_bit_data = {
.setsda = bit_i810ddc_setsda,
.setscl = bit_i810ddc_setscl,
.getsda = bit_i810ddc_getsda,
.getscl = bit_i810ddc_getscl,
.udelay = CYCLE_DELAY,
.timeout = TIMEOUT,
};
static struct i2c_adapter i810_ddc_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_B_I810,
.name = "I810/I815 DDC Adapter",
.algo_data = &i810_ddc_bit_data,
};
static struct pci_device_id i810_ids[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) },
{ 0, },
};
MODULE_DEVICE_TABLE (pci, i810_ids);
static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int retval;
retval = config_i810(dev);
if (retval)
return retval;
dev_info(&dev->dev, "i810/i815 i2c device found.\n");
/* set up the sysfs linkage to our parent device */
i810_i2c_adapter.dev.parent = &dev->dev;
i810_ddc_adapter.dev.parent = &dev->dev;
retval = i2c_bit_add_bus(&i810_i2c_adapter);
if (retval)
return retval;
retval = i2c_bit_add_bus(&i810_ddc_adapter);
if (retval)
i2c_del_adapter(&i810_i2c_adapter);
return retval;
}
static void __devexit i810_remove(struct pci_dev *dev)
{
i2c_del_adapter(&i810_ddc_adapter);
i2c_del_adapter(&i810_i2c_adapter);
iounmap(ioaddr);
}
static struct pci_driver i810_driver = {
.name = "i810_smbus",
.id_table = i810_ids,
.probe = i810_probe,
.remove = __devexit_p(i810_remove),
};
static int __init i2c_i810_init(void)
{
return pci_register_driver(&i810_driver);
}
static void __exit i2c_i810_exit(void)
{
pci_unregister_driver(&i810_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge.com>, "
"Ralph Metzler <rjkm@thp.uni-koeln.de>, "
"and Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
MODULE_LICENSE("GPL");
module_init(i2c_i810_init);
module_exit(i2c_i810_exit);

View File

@ -42,13 +42,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h> #include <linux/i2c-id.h>
#ifdef CONFIG_IBM_OCP
#include <asm/ocp.h>
#include <asm/ibm4xx.h>
#else
#include <linux/of_platform.h> #include <linux/of_platform.h>
#endif #include <linux/of_i2c.h>
#include "i2c-ibm_iic.h" #include "i2c-ibm_iic.h"
@ -665,180 +660,6 @@ static inline u8 iic_clckdiv(unsigned int opb)
return (u8)((opb + 9) / 10 - 1); return (u8)((opb + 9) / 10 - 1);
} }
#ifdef CONFIG_IBM_OCP
/*
* Register single IIC interface
*/
static int __devinit iic_probe(struct ocp_device *ocp){
struct ibm_iic_private* dev;
struct i2c_adapter* adap;
struct ocp_func_iic_data* iic_data = ocp->def->additions;
int ret;
if (!iic_data)
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
ocp->def->index);
if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
ocp->def->index);
return -ENOMEM;
}
dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev);
if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
"ibm_iic")) {
ret = -EBUSY;
goto fail1;
}
if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
dev->idx);
ret = -ENXIO;
goto fail2;
}
init_waitqueue_head(&dev->wq);
dev->irq = iic_force_poll ? -1 : ocp->def->irq;
if (dev->irq >= 0){
/* Disable interrupts until we finish initialization,
assumes level-sensitive IRQ setup...
*/
iic_interrupt_mode(dev, 0);
if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
dev->idx, dev->irq);
/* Fallback to the polling mode */
dev->irq = -1;
}
}
if (dev->irq < 0)
printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
dev->idx);
/* Board specific settings */
dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
/* clckdiv is the same for *all* IIC interfaces,
* but I'd rather make a copy than introduce another global. --ebs
*/
dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
/* Initialize IIC interface */
iic_dev_init(dev);
/* Register it with i2c layer */
adap = &dev->adap;
adap->dev.parent = &ocp->dev;
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON;
adap->algo = &iic_algo;
adap->client_register = NULL;
adap->client_unregister = NULL;
adap->timeout = 1;
/*
* If "dev->idx" is negative we consider it as zero.
* The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters.
*/
adap->nr = dev->idx >= 0 ? dev->idx : 0;
if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
dev->idx);
goto fail;
}
printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
return 0;
fail:
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
fail2:
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
fail1:
ocp_set_drvdata(ocp, NULL);
kfree(dev);
return ret;
}
/*
* Cleanup initialized IIC interface
*/
static void __devexit iic_remove(struct ocp_device *ocp)
{
struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
BUG_ON(dev == NULL);
if (i2c_del_adapter(&dev->adap)){
printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
dev->idx);
/* That's *very* bad, just shutdown IRQ ... */
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
dev->irq = -1;
}
} else {
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
kfree(dev);
}
}
static struct ocp_device_id ibm_iic_ids[] __devinitdata =
{
{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
{ .vendor = OCP_VENDOR_INVALID }
};
MODULE_DEVICE_TABLE(ocp, ibm_iic_ids);
static struct ocp_driver ibm_iic_driver =
{
.name = "iic",
.id_table = ibm_iic_ids,
.probe = iic_probe,
.remove = __devexit_p(iic_remove),
#if defined(CONFIG_PM)
.suspend = NULL,
.resume = NULL,
#endif
};
static int __init iic_init(void)
{
printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
return ocp_register_driver(&ibm_iic_driver);
}
static void __exit iic_exit(void)
{
ocp_unregister_driver(&ibm_iic_driver);
}
#else /* !CONFIG_IBM_OCP */
static int __devinit iic_request_irq(struct of_device *ofdev, static int __devinit iic_request_irq(struct of_device *ofdev,
struct ibm_iic_private *dev) struct ibm_iic_private *dev)
{ {
@ -876,7 +697,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
struct device_node *np = ofdev->node; struct device_node *np = ofdev->node;
struct ibm_iic_private *dev; struct ibm_iic_private *dev;
struct i2c_adapter *adap; struct i2c_adapter *adap;
const u32 *indexp, *freq; const u32 *freq;
int ret; int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@ -887,14 +708,6 @@ static int __devinit iic_probe(struct of_device *ofdev,
dev_set_drvdata(&ofdev->dev, dev); dev_set_drvdata(&ofdev->dev, dev);
indexp = of_get_property(np, "index", NULL);
if (!indexp) {
dev_err(&ofdev->dev, "no index specified\n");
ret = -EINVAL;
goto error_cleanup;
}
dev->idx = *indexp;
dev->vaddr = of_iomap(np, 0); dev->vaddr = of_iomap(np, 0);
if (dev->vaddr == NULL) { if (dev->vaddr == NULL) {
dev_err(&ofdev->dev, "failed to iomap device\n"); dev_err(&ofdev->dev, "failed to iomap device\n");
@ -934,17 +747,19 @@ static int __devinit iic_probe(struct of_device *ofdev,
strlcpy(adap->name, "IBM IIC", sizeof(adap->name)); strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP; adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &iic_algo; adap->algo = &iic_algo;
adap->timeout = 1; adap->timeout = 1;
adap->nr = dev->idx;
ret = i2c_add_numbered_adapter(adap); ret = i2c_add_adapter(adap);
if (ret < 0) { if (ret < 0) {
dev_err(&ofdev->dev, "failed to register i2c adapter\n"); dev_err(&ofdev->dev, "failed to register i2c adapter\n");
goto error_cleanup; goto error_cleanup;
} }
/* Now register all the child nodes */
of_register_i2c_devices(adap, np);
dev_info(&ofdev->dev, "using %s mode\n", dev_info(&ofdev->dev, "using %s mode\n",
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
@ -987,11 +802,7 @@ static int __devexit iic_remove(struct of_device *ofdev)
} }
static const struct of_device_id ibm_iic_match[] = { static const struct of_device_id ibm_iic_match[] = {
{ .compatible = "ibm,iic-405ex", }, { .compatible = "ibm,iic", },
{ .compatible = "ibm,iic-405gp", },
{ .compatible = "ibm,iic-440gp", },
{ .compatible = "ibm,iic-440gpx", },
{ .compatible = "ibm,iic-440grx", },
{} {}
}; };
@ -1011,7 +822,6 @@ static void __exit iic_exit(void)
{ {
of_unregister_platform_driver(&ibm_iic_driver); of_unregister_platform_driver(&ibm_iic_driver);
} }
#endif /* CONFIG_IBM_OCP */
module_init(iic_init); module_init(iic_init);
module_exit(iic_exit); module_exit(iic_exit);

View File

@ -482,7 +482,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
new_adapter->id = I2C_HW_IOP3XX; new_adapter->id = I2C_HW_IOP3XX;
new_adapter->owner = THIS_MODULE; new_adapter->owner = THIS_MODULE;
new_adapter->class = I2C_CLASS_HWMON; new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
new_adapter->dev.parent = &pdev->dev; new_adapter->dev.parent = &pdev->dev;
new_adapter->nr = pdev->id; new_adapter->nr = pdev->id;

View File

@ -0,0 +1,339 @@
/*
i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus
- Based on i2c-piix4.c
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com>
- Intel SCH support
Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com>
This program 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.
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.
*/
/*
Supports:
Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L)
Note: we assume there can only be one device, with one SMBus interface.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/stddef.h>
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/acpi.h>
/* SCH SMBus address offsets */
#define SMBHSTCNT (0 + sch_smba)
#define SMBHSTSTS (1 + sch_smba)
#define SMBHSTADD (4 + sch_smba) /* TSA */
#define SMBHSTCMD (5 + sch_smba)
#define SMBHSTDAT0 (6 + sch_smba)
#define SMBHSTDAT1 (7 + sch_smba)
#define SMBBLKDAT (0x20 + sch_smba)
/* count for request_region */
#define SMBIOSIZE 64
/* PCI Address Constants */
#define SMBBA_SCH 0x40
/* Other settings */
#define MAX_TIMEOUT 500
/* I2C constants */
#define SCH_QUICK 0x00
#define SCH_BYTE 0x01
#define SCH_BYTE_DATA 0x02
#define SCH_WORD_DATA 0x03
#define SCH_BLOCK_DATA 0x05
static unsigned short sch_smba;
static struct pci_driver sch_driver;
static struct i2c_adapter sch_adapter;
/*
* Start the i2c transaction -- the i2c_access will prepare the transaction
* and this function will execute it.
* return 0 for success and others for failure.
*/
static int sch_transaction(void)
{
int temp;
int result = 0;
int timeout = 0;
dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
inb(SMBHSTDAT1));
/* Make sure the SMBus host is ready to start transmitting */
temp = inb(SMBHSTSTS) & 0x0f;
if (temp) {
/* Can not be busy since we checked it in sch_access */
if (temp & 0x01) {
dev_dbg(&sch_adapter.dev, "Completion (%02x). "
"Clear...\n", temp);
}
if (temp & 0x06) {
dev_dbg(&sch_adapter.dev, "SMBus error (%02x). "
"Resetting...\n", temp);
}
outb(temp, SMBHSTSTS);
temp = inb(SMBHSTSTS) & 0x0f;
if (temp) {
dev_err(&sch_adapter.dev,
"SMBus is not ready: (%02x)\n", temp);
return -EAGAIN;
}
}
/* start the transaction by setting bit 4 */
outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
do {
msleep(1);
temp = inb(SMBHSTSTS) & 0x0f;
} while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) {
dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
if (temp & 0x04) {
result = -EIO;
dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
} else if (temp & 0x02) {
result = -EIO;
dev_err(&sch_adapter.dev, "Error: no response!\n");
} else if (temp & 0x01) {
dev_dbg(&sch_adapter.dev, "Post complete!\n");
outb(temp, SMBHSTSTS);
temp = inb(SMBHSTSTS) & 0x07;
if (temp & 0x06) {
/* Completion clear failed */
dev_dbg(&sch_adapter.dev, "Failed reset at end of "
"transaction (%02x), Bus error!\n", temp);
}
} else {
result = -ENXIO;
dev_dbg(&sch_adapter.dev, "No such address.\n");
}
dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
inb(SMBHSTDAT1));
return result;
}
/*
* This is the main access entry for i2c-sch access
* adap is i2c_adapter pointer, addr is the i2c device bus address, read_write
* (0 for read and 1 for write), size is i2c transaction type and data is the
* union of transaction for data to be transfered or data read from bus.
* return 0 for success and others for failure.
*/
static s32 sch_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
int i, len, temp, rc;
/* Make sure the SMBus host is not busy */
temp = inb(SMBHSTSTS) & 0x0f;
if (temp & 0x08) {
dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp);
return -EAGAIN;
}
dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size,
(read_write)?"READ":"WRITE");
switch (size) {
case I2C_SMBUS_QUICK:
outb((addr << 1) | read_write, SMBHSTADD);
size = SCH_QUICK;
break;
case I2C_SMBUS_BYTE:
outb((addr << 1) | read_write, SMBHSTADD);
if (read_write == I2C_SMBUS_WRITE)
outb(command, SMBHSTCMD);
size = SCH_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
outb((addr << 1) | read_write, SMBHSTADD);
outb(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE)
outb(data->byte, SMBHSTDAT0);
size = SCH_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
outb((addr << 1) | read_write, SMBHSTADD);
outb(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
outb(data->word & 0xff, SMBHSTDAT0);
outb((data->word & 0xff00) >> 8, SMBHSTDAT1);
}
size = SCH_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
outb((addr << 1) | read_write, SMBHSTADD);
outb(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0];
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
return -EINVAL;
outb(len, SMBHSTDAT0);
for (i = 1; i <= len; i++)
outb(data->block[i], SMBBLKDAT+i-1);
}
size = SCH_BLOCK_DATA;
break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
}
dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT);
outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT);
rc = sch_transaction();
if (rc) /* Error in transaction */
return rc;
if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK))
return 0;
switch (size) {
case SCH_BYTE:
case SCH_BYTE_DATA:
data->byte = inb(SMBHSTDAT0);
break;
case SCH_WORD_DATA:
data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8);
break;
case SCH_BLOCK_DATA:
data->block[0] = inb(SMBHSTDAT0);
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb(SMBBLKDAT+i-1);
break;
}
return 0;
}
static u32 sch_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA;
}
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = sch_access,
.functionality = sch_func,
};
static struct i2c_adapter sch_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
static struct pci_device_id sch_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, sch_ids);
static int __devinit sch_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
int retval;
unsigned int smba;
pci_read_config_dword(dev, SMBBA_SCH, &smba);
if (!(smba & (1 << 31))) {
dev_err(&dev->dev, "SMBus I/O space disabled!\n");
return -ENODEV;
}
sch_smba = (unsigned short)smba;
if (sch_smba == 0) {
dev_err(&dev->dev, "SMBus base address uninitialized!\n");
return -ENODEV;
}
if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
return -EBUSY;
if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
sch_smba);
return -EBUSY;
}
dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
/* set up the sysfs linkage to our parent device */
sch_adapter.dev.parent = &dev->dev;
snprintf(sch_adapter.name, sizeof(sch_adapter.name),
"SMBus SCH adapter at %04x", sch_smba);
retval = i2c_add_adapter(&sch_adapter);
if (retval) {
dev_err(&dev->dev, "Couldn't register adapter!\n");
release_region(sch_smba, SMBIOSIZE);
sch_smba = 0;
}
return retval;
}
static void __devexit sch_remove(struct pci_dev *dev)
{
if (sch_smba) {
i2c_del_adapter(&sch_adapter);
release_region(sch_smba, SMBIOSIZE);
sch_smba = 0;
}
}
static struct pci_driver sch_driver = {
.name = "isch_smbus",
.id_table = sch_ids,
.probe = sch_probe,
.remove = __devexit_p(sch_remove),
};
static int __init i2c_sch_init(void)
{
return pci_register_driver(&sch_driver);
}
static void __exit i2c_sch_exit(void)
{
pci_unregister_driver(&sch_driver);
}
MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
MODULE_DESCRIPTION("Intel SCH SMBus driver");
MODULE_LICENSE("GPL");
module_init(i2c_sch_init);
module_exit(i2c_sch_exit);

View File

@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = {
.name = "MPC adapter", .name = "MPC adapter",
.id = I2C_HW_MPC107, .id = I2C_HW_MPC107,
.algo = &mpc_algo, .algo = &mpc_algo,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.timeout = 1, .timeout = 1,
}; };

View File

@ -530,7 +530,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->adapter.id = I2C_HW_MV64XXX; drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE; drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON; drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
drv_data->adapter.timeout = pdata->timeout; drv_data->adapter.timeout = pdata->timeout;
drv_data->adapter.nr = pd->id; drv_data->adapter.nr = pd->id;
platform_set_drvdata(pd, drv_data); platform_set_drvdata(pd, drv_data);

View File

@ -0,0 +1,257 @@
/*
* i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard
*
* Copyright (C) 2008 Jean Delvare <khali@linux-fr.org>
*
* 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.
*/
/*
* We select the channels by sending commands to the Philips
* PCA9556 chip at I2C address 0x18. The main adapter is used for
* the non-multiplexed part of the bus, and 4 virtual adapters
* are defined for the multiplexed addresses: 0x50-0x53 (memory
* module EEPROM) located on channels 1-4. We define one virtual
* adapter per CPU, which corresponds to one multiplexed channel:
* CPU0: virtual adapter 1, channel 1
* CPU1: virtual adapter 2, channel 2
* CPU2: virtual adapter 3, channel 3
* CPU3: virtual adapter 4, channel 4
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
extern struct i2c_adapter *nforce2_smbus;
static struct i2c_adapter *s4985_adapter;
static struct i2c_algorithm *s4985_algo;
/* Wrapper access functions for multiplexed SMBus */
static DEFINE_MUTEX(nforce2_lock);
static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
int error;
/* We exclude the multiplexed addresses */
if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
|| addr == 0x18)
return -ENXIO;
mutex_lock(&nforce2_lock);
error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
command, size, data);
mutex_unlock(&nforce2_lock);
return error;
}
/* We remember the last used channels combination so as to only switch
channels when it is really needed. This greatly reduces the SMBus
overhead, but also assumes that nobody will be writing to the PCA9556
in our back. */
static u8 last_channels;
static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data,
u8 channels)
{
int error;
/* We exclude the non-multiplexed addresses */
if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
return -ENXIO;
mutex_lock(&nforce2_lock);
if (last_channels != channels) {
union i2c_smbus_data mplxdata;
mplxdata.byte = channels;
error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0,
I2C_SMBUS_WRITE, 0x01,
I2C_SMBUS_BYTE_DATA,
&mplxdata);
if (error)
goto UNLOCK;
last_channels = channels;
}
error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
command, size, data);
UNLOCK:
mutex_unlock(&nforce2_lock);
return error;
}
static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
/* CPU0: channel 1 enabled */
return nforce2_access_channel(adap, addr, flags, read_write, command,
size, data, 0x02);
}
static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
/* CPU1: channel 2 enabled */
return nforce2_access_channel(adap, addr, flags, read_write, command,
size, data, 0x04);
}
static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
/* CPU2: channel 3 enabled */
return nforce2_access_channel(adap, addr, flags, read_write, command,
size, data, 0x08);
}
static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
/* CPU3: channel 4 enabled */
return nforce2_access_channel(adap, addr, flags, read_write, command,
size, data, 0x10);
}
static int __init nforce2_s4985_init(void)
{
int i, error;
union i2c_smbus_data ioconfig;
/* Unregister physical bus */
if (!nforce2_smbus)
return -ENODEV;
error = i2c_del_adapter(nforce2_smbus);
if (error) {
dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n");
goto ERROR0;
}
printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
/* Define the 5 virtual adapters and algorithms structures */
s4985_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL);
if (!s4985_adapter) {
error = -ENOMEM;
goto ERROR1;
}
s4985_algo = kzalloc(5 * sizeof(struct i2c_algorithm), GFP_KERNEL);
if (!s4985_algo) {
error = -ENOMEM;
goto ERROR2;
}
/* Fill in the new structures */
s4985_algo[0] = *(nforce2_smbus->algo);
s4985_algo[0].smbus_xfer = nforce2_access_virt0;
s4985_adapter[0] = *nforce2_smbus;
s4985_adapter[0].algo = s4985_algo;
s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent;
for (i = 1; i < 5; i++) {
s4985_algo[i] = *(nforce2_smbus->algo);
s4985_adapter[i] = *nforce2_smbus;
snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name),
"SMBus nForce2 adapter (CPU%d)", i - 1);
s4985_adapter[i].algo = s4985_algo + i;
s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent;
}
s4985_algo[1].smbus_xfer = nforce2_access_virt1;
s4985_algo[2].smbus_xfer = nforce2_access_virt2;
s4985_algo[3].smbus_xfer = nforce2_access_virt3;
s4985_algo[4].smbus_xfer = nforce2_access_virt4;
/* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */
error = nforce2_smbus->algo->smbus_xfer(nforce2_smbus, 0x18, 0,
I2C_SMBUS_WRITE, 0x03,
I2C_SMBUS_BYTE_DATA, &ioconfig);
if (error) {
dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
error = -EIO;
goto ERROR3;
}
/* Register virtual adapters */
for (i = 0; i < 5; i++) {
error = i2c_add_adapter(s4985_adapter + i);
if (error) {
dev_err(&nforce2_smbus->dev,
"Virtual adapter %d registration "
"failed, module not inserted\n", i);
for (i--; i >= 0; i--)
i2c_del_adapter(s4985_adapter + i);
goto ERROR3;
}
}
return 0;
ERROR3:
kfree(s4985_algo);
s4985_algo = NULL;
ERROR2:
kfree(s4985_adapter);
s4985_adapter = NULL;
ERROR1:
/* Restore physical bus */
i2c_add_adapter(nforce2_smbus);
ERROR0:
return error;
}
static void __exit nforce2_s4985_exit(void)
{
if (s4985_adapter) {
int i;
for (i = 0; i < 5; i++)
i2c_del_adapter(s4985_adapter+i);
kfree(s4985_adapter);
s4985_adapter = NULL;
}
kfree(s4985_algo);
s4985_algo = NULL;
/* Restore physical bus */
if (i2c_add_adapter(nforce2_smbus))
dev_err(&nforce2_smbus->dev, "Physical bus restoration "
"failed\n");
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("S4985 SMBus multiplexing");
MODULE_LICENSE("GPL");
module_init(nforce2_s4985_init);
module_exit(nforce2_s4985_exit);

View File

@ -51,6 +51,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -124,6 +125,20 @@ static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
static struct pci_driver nforce2_driver; static struct pci_driver nforce2_driver;
/* For multiplexing support, we need a global reference to the 1st
SMBus channel */
#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE
struct i2c_adapter *nforce2_smbus;
EXPORT_SYMBOL_GPL(nforce2_smbus);
static void nforce2_set_reference(struct i2c_adapter *adap)
{
nforce2_smbus = adap;
}
#else
static inline void nforce2_set_reference(struct i2c_adapter *adap) { }
#endif
static void nforce2_abort(struct i2c_adapter *adap) static void nforce2_abort(struct i2c_adapter *adap)
{ {
struct nforce2_smbus *smbus = adap->algo_data; struct nforce2_smbus *smbus = adap->algo_data;
@ -158,16 +173,16 @@ static int nforce2_check_status(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "SMBus Timeout!\n"); dev_dbg(&adap->dev, "SMBus Timeout!\n");
if (smbus->can_abort) if (smbus->can_abort)
nforce2_abort(adap); nforce2_abort(adap);
return -1; return -ETIMEDOUT;
} }
if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) { if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp); dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp);
return -1; return -EIO;
} }
return 0; return 0;
} }
/* Return -1 on error */ /* Return negative errno on error */
static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
@ -175,7 +190,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
struct nforce2_smbus *smbus = adap->algo_data; struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec; unsigned char protocol, pec;
u8 len; u8 len;
int i; int i, status;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
NVIDIA_SMB_PRTCL_WRITE; NVIDIA_SMB_PRTCL_WRITE;
@ -219,7 +234,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
"Transaction failed " "Transaction failed "
"(requested block size: %d)\n", "(requested block size: %d)\n",
len); len);
return -1; return -EINVAL;
} }
outb_p(len, NVIDIA_SMB_BCNT); outb_p(len, NVIDIA_SMB_BCNT);
for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
@ -231,14 +246,15 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
default: default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size); dev_err(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
} }
outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR); outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
outb_p(protocol, NVIDIA_SMB_PRTCL); outb_p(protocol, NVIDIA_SMB_PRTCL);
if (nforce2_check_status(adap)) status = nforce2_check_status(adap);
return -1; if (status)
return status;
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
return 0; return 0;
@ -260,7 +276,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
dev_err(&adap->dev, "Transaction failed " dev_err(&adap->dev, "Transaction failed "
"(received block size: 0x%02x)\n", "(received block size: 0x%02x)\n",
len); len);
return -1; return -EPROTO;
} }
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
@ -321,21 +337,26 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
!= PCIBIOS_SUCCESSFUL) { != PCIBIOS_SUCCESSFUL) {
dev_err(&dev->dev, "Error reading PCI config for %s\n", dev_err(&dev->dev, "Error reading PCI config for %s\n",
name); name);
return -1; return -EIO;
} }
smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
smbus->size = 64; smbus->size = 64;
} }
error = acpi_check_region(smbus->base, smbus->size,
nforce2_driver.name);
if (error)
return -1;
if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
smbus->base, smbus->base+smbus->size-1, name); smbus->base, smbus->base+smbus->size-1, name);
return -1; return -EBUSY;
} }
smbus->adapter.owner = THIS_MODULE; smbus->adapter.owner = THIS_MODULE;
smbus->adapter.id = I2C_HW_SMBUS_NFORCE2; smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
smbus->adapter.dev.parent = &dev->dev; smbus->adapter.dev.parent = &dev->dev;
@ -346,7 +367,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
if (error) { if (error) {
dev_err(&smbus->adapter.dev, "Failed to register adapter.\n"); dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
release_region(smbus->base, smbus->size); release_region(smbus->base, smbus->size);
return -1; return error;
} }
dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base); dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base);
return 0; return 0;
@ -398,6 +419,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
return -ENODEV; return -ENODEV;
} }
nforce2_set_reference(&smbuses[0].adapter);
return 0; return 0;
} }
@ -406,6 +428,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
{ {
struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev); struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
nforce2_set_reference(NULL);
if (smbuses[0].base) { if (smbuses[0].base) {
i2c_del_adapter(&smbuses[0].adapter); i2c_del_adapter(&smbuses[0].adapter);
release_region(smbuses[0].base, smbuses[0].size); release_region(smbuses[0].base, smbuses[0].size);

View File

@ -29,6 +29,7 @@ struct ocores_i2c {
int pos; int pos;
int nmsgs; int nmsgs;
int state; /* see STATE_ */ int state; /* see STATE_ */
int clock_khz;
}; };
/* registers */ /* registers */
@ -173,8 +174,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static void ocores_init(struct ocores_i2c *i2c, static void ocores_init(struct ocores_i2c *i2c)
struct ocores_i2c_platform_data *pdata)
{ {
int prescale; int prescale;
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
@ -182,7 +182,7 @@ static void ocores_init(struct ocores_i2c *i2c,
/* make sure the device is disabled */ /* make sure the device is disabled */
oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
prescale = (pdata->clock_khz / (5*100)) - 1; prescale = (i2c->clock_khz / (5*100)) - 1;
oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
@ -205,7 +205,7 @@ static const struct i2c_algorithm ocores_algorithm = {
static struct i2c_adapter ocores_adapter = { static struct i2c_adapter ocores_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "i2c-ocores", .name = "i2c-ocores",
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ocores_algorithm, .algo = &ocores_algorithm,
}; };
@ -248,7 +248,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
} }
i2c->regstep = pdata->regstep; i2c->regstep = pdata->regstep;
ocores_init(i2c, pdata); i2c->clock_khz = pdata->clock_khz;
ocores_init(i2c);
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c); ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c);
@ -312,13 +313,40 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state)
{
struct ocores_i2c *i2c = platform_get_drvdata(pdev);
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
/* make sure the device is disabled */
oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
return 0;
}
static int ocores_i2c_resume(struct platform_device *pdev)
{
struct ocores_i2c *i2c = platform_get_drvdata(pdev);
ocores_init(i2c);
return 0;
}
#else
#define ocores_i2c_suspend NULL
#define ocores_i2c_resume NULL
#endif
/* work with hotplug and coldplug */ /* work with hotplug and coldplug */
MODULE_ALIAS("platform:ocores-i2c"); MODULE_ALIAS("platform:ocores-i2c");
static struct platform_driver ocores_i2c_driver = { static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe, .probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove), .remove = __devexit_p(ocores_i2c_remove),
.driver = { .suspend = ocores_i2c_suspend,
.resume = ocores_i2c_resume,
.driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ocores-i2c", .name = "ocores-i2c",
}, },

View File

@ -365,7 +365,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.owner = THIS_MODULE; smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"PA Semi SMBus adapter at 0x%lx", smbus->base); "PA Semi SMBus adapter at 0x%lx", smbus->base);
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
smbus->adapter.nr = PCI_FUNC(dev->devfn); smbus->adapter.nr = PCI_FUNC(dev->devfn);

View File

@ -163,7 +163,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
i2c->reg_base = ioremap(res->start, res_len(res)); i2c->reg_base = ioremap(res->start, res_len(res));
if (!i2c->reg_base) { if (!i2c->reg_base) {
ret = -EIO; ret = -ENOMEM;
goto e_remap; goto e_remap;
} }
i2c->io_base = res->start; i2c->io_base = res->start;

View File

@ -1,6 +1,4 @@
/* /*
piix4.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com> Philip Edelbrock <phil@netroedge.com>
@ -39,16 +37,10 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
struct sd {
const unsigned short mfr;
const unsigned short dev;
const unsigned char fn;
const char *name;
};
/* PIIX4 SMBus address offsets */ /* PIIX4 SMBus address offsets */
#define SMBHSTSTS (0 + piix4_smba) #define SMBHSTSTS (0 + piix4_smba)
#define SMBHSLVSTS (1 + piix4_smba) #define SMBHSLVSTS (1 + piix4_smba)
@ -101,8 +93,6 @@ MODULE_PARM_DESC(force_addr,
"Forcibly enable the PIIX4 at the given address. " "Forcibly enable the PIIX4 at the given address. "
"EXTREMELY DANGEROUS!"); "EXTREMELY DANGEROUS!");
static int piix4_transaction(void);
static unsigned short piix4_smba; static unsigned short piix4_smba;
static int srvrworks_csb5_delay; static int srvrworks_csb5_delay;
static struct pci_driver piix4_driver; static struct pci_driver piix4_driver;
@ -141,8 +131,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
{ {
unsigned char temp; unsigned char temp;
dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) && if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
(PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5)) (PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5))
srvrworks_csb5_delay = 1; srvrworks_csb5_delay = 1;
@ -172,17 +160,20 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
piix4_smba &= 0xfff0; piix4_smba &= 0xfff0;
if(piix4_smba == 0) { if(piix4_smba == 0) {
dev_err(&PIIX4_dev->dev, "SMB base address " dev_err(&PIIX4_dev->dev, "SMBus base address "
"uninitialized - upgrade BIOS or use " "uninitialized - upgrade BIOS or use "
"force_addr=0xaddr\n"); "force_addr=0xaddr\n");
return -ENODEV; return -ENODEV;
} }
} }
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
return -EBUSY;
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n", dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
piix4_smba); piix4_smba);
return -ENODEV; return -EBUSY;
} }
pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
@ -228,13 +219,13 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
"(or code out of date)!\n"); "(or code out of date)!\n");
pci_read_config_byte(PIIX4_dev, SMBREV, &temp); pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp); dev_info(&PIIX4_dev->dev,
dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba); "SMBus Host Controller at 0x%x, revision %d\n",
piix4_smba, temp);
return 0; return 0;
} }
/* Another internally used function */
static int piix4_transaction(void) static int piix4_transaction(void)
{ {
int temp; int temp;
@ -253,7 +244,7 @@ static int piix4_transaction(void)
outb_p(temp, SMBHSTSTS); outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) != 0x00) { if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
return -1; return -EBUSY;
} else { } else {
dev_dbg(&piix4_adapter.dev, "Successful!\n"); dev_dbg(&piix4_adapter.dev, "Successful!\n");
} }
@ -275,23 +266,23 @@ static int piix4_transaction(void)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); dev_err(&piix4_adapter.dev, "SMBus Timeout!\n");
result = -1; result = -ETIMEDOUT;
} }
if (temp & 0x10) { if (temp & 0x10) {
result = -1; result = -EIO;
dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n"); dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n");
} }
if (temp & 0x08) { if (temp & 0x08) {
result = -1; result = -EIO;
dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be " dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n"); "locked until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */ /* Clock stops and slave is stuck in mid-transmission */
} }
if (temp & 0x04) { if (temp & 0x04) {
result = -1; result = -ENXIO;
dev_dbg(&piix4_adapter.dev, "Error: no response!\n"); dev_dbg(&piix4_adapter.dev, "Error: no response!\n");
} }
@ -309,31 +300,29 @@ static int piix4_transaction(void)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 piix4_access(struct i2c_adapter * adap, u16 addr, static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
{ {
int i, len; int i, len;
int status;
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p((addr << 1) | read_write,
SMBHSTADD); SMBHSTADD);
size = PIIX4_QUICK; size = PIIX4_QUICK;
break; break;
case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p((addr << 1) | read_write,
SMBHSTADD); SMBHSTADD);
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
outb_p(command, SMBHSTCMD); outb_p(command, SMBHSTCMD);
size = PIIX4_BYTE; size = PIIX4_BYTE;
break; break;
case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_BYTE_DATA:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p((addr << 1) | read_write,
SMBHSTADD); SMBHSTADD);
outb_p(command, SMBHSTCMD); outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
@ -341,7 +330,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
size = PIIX4_BYTE_DATA; size = PIIX4_BYTE_DATA;
break; break;
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p((addr << 1) | read_write,
SMBHSTADD); SMBHSTADD);
outb_p(command, SMBHSTCMD); outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
@ -351,15 +340,13 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
size = PIIX4_WORD_DATA; size = PIIX4_WORD_DATA;
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p((addr << 1) | read_write,
SMBHSTADD); SMBHSTADD);
outb_p(command, SMBHSTCMD); outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0]; len = data->block[0];
if (len < 0) if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
len = 0; return -EINVAL;
if (len > 32)
len = 32;
outb_p(len, SMBHSTDAT0); outb_p(len, SMBHSTDAT0);
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++) for (i = 1; i <= len; i++)
@ -367,12 +354,16 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
} }
size = PIIX4_BLOCK_DATA; size = PIIX4_BLOCK_DATA;
break; break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
} }
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
if (piix4_transaction()) /* Error in transaction */ status = piix4_transaction();
return -1; if (status)
return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
return 0; return 0;
@ -388,6 +379,8 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
break; break;
case PIIX4_BLOCK_DATA: case PIIX4_BLOCK_DATA:
data->block[0] = inb_p(SMBHSTDAT0); data->block[0] = inb_p(SMBHSTDAT0);
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= data->block[0]; i++) for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT); data->block[i] = inb_p(SMBBLKDAT);
@ -411,7 +404,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter piix4_adapter = { static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_PIIX4, .id = I2C_HW_SMBUS_PIIX4,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };

View File

@ -622,7 +622,7 @@ static struct i2c_algorithm pmcmsptwi_algo = {
static struct i2c_adapter pmcmsptwi_adapter = { static struct i2c_adapter pmcmsptwi_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &pmcmsptwi_algo, .algo = &pmcmsptwi_algo,
.name = DRV_NAME, .name = DRV_NAME,
}; };

View File

@ -1,325 +0,0 @@
/*
* kernel/busses/i2c-prosavage.c
*
* i2c bus driver for S3/VIA 8365/8375 graphics processor.
* Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org>
* Based on code written by:
* Frodo Looijaard <frodol@dds.nl>,
* Philip Edelbrock <phil@netroedge.com>,
* Ralph Metzler <rjkm@thp.uni-koeln.de>, and
* Mark D. Studebaker <mdsxyz123@yahoo.com>
* Simon Vogl
* and others
*
* Please read the lm_sensors documentation for details on use.
*
* 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.
*
*/
/* 18-05-2003 HVE - created
* 14-06-2003 HVE - adapted for lm_sensors2
* 17-06-2003 HVE - linux 2.5.xx compatible
* 18-06-2003 HVE - codingstyle
* 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx
* codingstyle, mmio enabled
*
* This driver interfaces to the I2C bus of the VIA north bridge embedded
* ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips.
*
* Graphics cores:
* S3/VIA KM266/VT8375 aka ProSavage8
* S3/VIA KM133/VT8365 aka Savage4
*
* Two serial busses are implemented:
* SERIAL1 - I2C serial communications interface
* SERIAL2 - DDC2 monitor communications interface
*
* Tested on a FX41 mainboard, see http://www.shuttle.com
*
*
* TODO:
* - integration with prosavage framebuffer device
* (Additional documentation needed :(
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/io.h>
/*
* driver configuration
*/
#define MAX_BUSSES 2
struct s_i2c_bus {
void __iomem *mmvga;
int i2c_reg;
int adap_ok;
struct i2c_adapter adap;
struct i2c_algo_bit_data algo;
};
struct s_i2c_chip {
void __iomem *mmio;
struct s_i2c_bus i2c_bus[MAX_BUSSES];
};
/*
* i2c configuration
*/
#define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2)
/*
* S3/VIA 8365/8375 registers
*/
#define VGA_CR_IX 0x3d4
#define VGA_CR_DATA 0x3d5
#define CR_SERIAL1 0xa0 /* I2C serial communications interface */
#define MM_SERIAL1 0xff20
#define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
/* based on vt8365 documentation */
#define I2C_ENAB 0x10
#define I2C_SCL_OUT 0x01
#define I2C_SDA_OUT 0x02
#define I2C_SCL_IN 0x04
#define I2C_SDA_IN 0x08
#define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX)
#define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA)
#define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA)
/*
* Serial bus line handling
*
* serial communications register as parameter in private data
*
* TODO: locks with other code sections accessing video registers?
*/
static void bit_s3via_setscl(void *bus, int val)
{
struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
unsigned int r;
SET_CR_IX(p, p->i2c_reg);
r = GET_CR_DATA(p);
r |= I2C_ENAB;
if (val) {
r |= I2C_SCL_OUT;
} else {
r &= ~I2C_SCL_OUT;
}
SET_CR_DATA(p, r);
}
static void bit_s3via_setsda(void *bus, int val)
{
struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
unsigned int r;
SET_CR_IX(p, p->i2c_reg);
r = GET_CR_DATA(p);
r |= I2C_ENAB;
if (val) {
r |= I2C_SDA_OUT;
} else {
r &= ~I2C_SDA_OUT;
}
SET_CR_DATA(p, r);
}
static int bit_s3via_getscl(void *bus)
{
struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
SET_CR_IX(p, p->i2c_reg);
return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
}
static int bit_s3via_getsda(void *bus)
{
struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
SET_CR_IX(p, p->i2c_reg);
return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
}
/*
* adapter initialisation
*/
static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
{
int ret;
p->adap.owner = THIS_MODULE;
p->adap.id = I2C_HW_B_S3VIA;
p->adap.algo_data = &p->algo;
p->adap.dev.parent = &dev->dev;
p->algo.setsda = bit_s3via_setsda;
p->algo.setscl = bit_s3via_setscl;
p->algo.getsda = bit_s3via_getsda;
p->algo.getscl = bit_s3via_getscl;
p->algo.udelay = CYCLE_DELAY;
p->algo.timeout = TIMEOUT;
p->algo.data = p;
p->mmvga = mmvga;
p->i2c_reg = i2c_reg;
ret = i2c_bit_add_bus(&p->adap);
if (ret) {
return ret;
}
p->adap_ok = 1;
return 0;
}
/*
* Cleanup stuff
*/
static void prosavage_remove(struct pci_dev *dev)
{
struct s_i2c_chip *chip;
int i, ret;
chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
if (!chip) {
return;
}
for (i = MAX_BUSSES - 1; i >= 0; i--) {
if (chip->i2c_bus[i].adap_ok == 0)
continue;
ret = i2c_del_adapter(&chip->i2c_bus[i].adap);
if (ret) {
dev_err(&dev->dev, "%s not removed\n",
chip->i2c_bus[i].adap.name);
}
}
if (chip->mmio) {
iounmap(chip->mmio);
}
kfree(chip);
}
/*
* Detect chip and initialize it
*/
static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int ret;
unsigned long base, len;
struct s_i2c_chip *chip;
struct s_i2c_bus *bus;
pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
if (chip == NULL) {
return -ENOMEM;
}
base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
len = dev->resource[0].end - base + 1;
chip->mmio = ioremap_nocache(base, len);
if (chip->mmio == NULL) {
dev_err(&dev->dev, "ioremap failed\n");
prosavage_remove(dev);
return -ENODEV;
}
/*
* Chip initialisation
*/
/* Unlock Extended IO Space ??? */
/*
* i2c bus registration
*/
bus = &chip->i2c_bus[0];
snprintf(bus->adap.name, sizeof(bus->adap.name),
"ProSavage I2C bus at %02x:%02x.%x",
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
if (ret) {
goto err_adap;
}
/*
* ddc bus registration
*/
bus = &chip->i2c_bus[1];
snprintf(bus->adap.name, sizeof(bus->adap.name),
"ProSavage DDC bus at %02x:%02x.%x",
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
if (ret) {
goto err_adap;
}
return 0;
err_adap:
dev_err(&dev->dev, "%s failed\n", bus->adap.name);
prosavage_remove(dev);
return ret;
}
/*
* Data for PCI driver interface
*/
static struct pci_device_id prosavage_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
{ PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
{ 0, },
};
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
static struct pci_driver prosavage_driver = {
.name = "prosavage_smbus",
.id_table = prosavage_pci_tbl,
.probe = prosavage_probe,
.remove = prosavage_remove,
};
static int __init i2c_prosavage_init(void)
{
return pci_register_driver(&prosavage_driver);
}
static void __exit i2c_prosavage_exit(void)
{
pci_unregister_driver(&prosavage_driver);
}
MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
MODULE_AUTHOR("Henk Vergonet");
MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
MODULE_LICENSE("GPL");
module_init (i2c_prosavage_init);
module_exit (i2c_prosavage_exit);

View File

@ -1104,5 +1104,5 @@ static void __exit i2c_adap_pxa_exit(void)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pxa2xx-i2c"); MODULE_ALIAS("platform:pxa2xx-i2c");
module_init(i2c_adap_pxa_init); subsys_initcall(i2c_adap_pxa_init);
module_exit(i2c_adap_pxa_exit); module_exit(i2c_adap_pxa_exit);

View File

@ -590,7 +590,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm, .algo = &s3c24xx_i2c_algorithm,
.retries = 2, .retries = 2,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
}, },
}; };

View File

@ -1,185 +0,0 @@
/*
i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (C) 1998-2003 The LM Sensors Team
Alexander Wold <awold@bigfoot.com>
Mark D. Studebaker <mdsxyz123@yahoo.com>
Based on i2c-voodoo3.c.
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.
*/
/* This interfaces to the I2C bus of the Savage4 to gain access to
the BT869 and possibly other I2C devices. The DDC bus is not
yet supported because its register is not memory-mapped.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/io.h>
/* device IDs */
#define PCI_CHIP_SAVAGE4 0x8A22
#define PCI_CHIP_SAVAGE2000 0x9102
#define REG 0xff20 /* Serial Port 1 Register */
/* bit locations in the register */
#define I2C_ENAB 0x00000020
#define I2C_SCL_OUT 0x00000001
#define I2C_SDA_OUT 0x00000002
#define I2C_SCL_IN 0x00000008
#define I2C_SDA_IN 0x00000010
/* delays */
#define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2)
static void __iomem *ioaddr;
/* The sav GPIO registers don't have individual masks for each bit
so we always have to read before writing. */
static void bit_savi2c_setscl(void *data, int val)
{
unsigned int r;
r = readl(ioaddr + REG);
if(val)
r |= I2C_SCL_OUT;
else
r &= ~I2C_SCL_OUT;
writel(r, ioaddr + REG);
readl(ioaddr + REG); /* flush posted write */
}
static void bit_savi2c_setsda(void *data, int val)
{
unsigned int r;
r = readl(ioaddr + REG);
if(val)
r |= I2C_SDA_OUT;
else
r &= ~I2C_SDA_OUT;
writel(r, ioaddr + REG);
readl(ioaddr + REG); /* flush posted write */
}
/* The GPIO pins are open drain, so the pins always remain outputs.
We rely on the i2c-algo-bit routines to set the pins high before
reading the input from other chips. */
static int bit_savi2c_getscl(void *data)
{
return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
}
static int bit_savi2c_getsda(void *data)
{
return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
}
/* Configures the chip */
static int config_s4(struct pci_dev *dev)
{
unsigned long cadr;
/* map memory */
cadr = dev->resource[0].start;
cadr &= PCI_BASE_ADDRESS_MEM_MASK;
ioaddr = ioremap_nocache(cadr, 0x0080000);
if (ioaddr) {
/* writel(0x8160, ioaddr + REG2); */
writel(0x00000020, ioaddr + REG);
dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr);
return 0;
}
return -ENODEV;
}
static struct i2c_algo_bit_data sav_i2c_bit_data = {
.setsda = bit_savi2c_setsda,
.setscl = bit_savi2c_setscl,
.getsda = bit_savi2c_getsda,
.getscl = bit_savi2c_getscl,
.udelay = CYCLE_DELAY,
.timeout = TIMEOUT
};
static struct i2c_adapter savage4_i2c_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_B_SAVAGE,
.name = "I2C Savage4 adapter",
.algo_data = &sav_i2c_bit_data,
};
static struct pci_device_id savage4_ids[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) },
{ PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) },
{ 0, }
};
MODULE_DEVICE_TABLE (pci, savage4_ids);
static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int retval;
retval = config_s4(dev);
if (retval)
return retval;
/* set up the sysfs linkage to our parent device */
savage4_i2c_adapter.dev.parent = &dev->dev;
return i2c_bit_add_bus(&savage4_i2c_adapter);
}
static void __devexit savage4_remove(struct pci_dev *dev)
{
i2c_del_adapter(&savage4_i2c_adapter);
iounmap(ioaddr);
}
static struct pci_driver savage4_driver = {
.name = "savage4_smbus",
.id_table = savage4_ids,
.probe = savage4_probe,
.remove = __devexit_p(savage4_remove),
};
static int __init i2c_savage4_init(void)
{
return pci_register_driver(&savage4_driver);
}
static void __exit i2c_savage4_exit(void)
{
pci_unregister_driver(&savage4_driver);
}
MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> "
"and Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("Savage4 I2C/SMBus driver");
MODULE_LICENSE("GPL");
module_init(i2c_savage4_init);
module_exit(i2c_savage4_exit);

View File

@ -143,7 +143,7 @@ static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
return i2c_add_adapter(i2c_adap); return i2c_add_numbered_adapter(i2c_adap);
} }
@ -156,17 +156,19 @@ static struct i2c_adapter sibyte_board_adapter[2] = {
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SIBYTE, .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL, .algo = NULL,
.algo_data = &sibyte_board_data[0], .algo_data = &sibyte_board_data[0],
.nr = 0,
.name = "SiByte SMBus 0", .name = "SiByte SMBus 0",
}, },
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SIBYTE, .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL, .algo = NULL,
.algo_data = &sibyte_board_data[1], .algo_data = &sibyte_board_data[1],
.nr = 1,
.name = "SiByte SMBus 1", .name = "SiByte SMBus 1",
}, },
}; };

View File

@ -1,6 +1,4 @@
/* /*
sis5595.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com> Philip Edelbrock <phil@netroedge.com>
@ -62,6 +60,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
static int blacklist[] = { static int blacklist[] = {
@ -174,6 +173,11 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev)
/* NB: We grab just the two SMBus registers here, but this may still /* NB: We grab just the two SMBus registers here, but this may still
* interfere with ACPI :-( */ * interfere with ACPI :-( */
retval = acpi_check_region(sis5595_base + SMB_INDEX, 2,
sis5595_driver.name);
if (retval)
return retval;
if (!request_region(sis5595_base + SMB_INDEX, 2, if (!request_region(sis5595_base + SMB_INDEX, 2,
sis5595_driver.name)) { sis5595_driver.name)) {
dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n", dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
@ -236,7 +240,7 @@ static int sis5595_transaction(struct i2c_adapter *adap)
sis5595_write(SMB_STS_HI, temp >> 8); sis5595_write(SMB_STS_HI, temp >> 8);
if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) { if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
return -1; return -EBUSY;
} else { } else {
dev_dbg(&adap->dev, "Successful!\n"); dev_dbg(&adap->dev, "Successful!\n");
} }
@ -254,19 +258,19 @@ static int sis5595_transaction(struct i2c_adapter *adap)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n"); dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -1; result = -ETIMEDOUT;
} }
if (temp & 0x10) { if (temp & 0x10) {
dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
result = -1; result = -ENXIO;
} }
if (temp & 0x20) { if (temp & 0x20) {
dev_err(&adap->dev, "Bus collision! SMBus may be locked until " dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
"next hard reset (or not...)\n"); "next hard reset (or not...)\n");
/* Clock stops and slave is stuck in mid-transmission */ /* Clock stops and slave is stuck in mid-transmission */
result = -1; result = -EIO;
} }
temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
@ -282,11 +286,13 @@ static int sis5595_transaction(struct i2c_adapter *adap)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 sis5595_access(struct i2c_adapter *adap, u16 addr, static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data) u8 command, int size, union i2c_smbus_data *data)
{ {
int status;
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
@ -318,13 +324,14 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
break; break;
default: default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size); dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
} }
sis5595_write(SMB_CTL_LO, ((size & 0x0E))); sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
if (sis5595_transaction(adap)) status = sis5595_transaction(adap);
return -1; if (status)
return status;
if ((size != SIS5595_PROC_CALL) && if ((size != SIS5595_PROC_CALL) &&
((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK))) ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
@ -359,7 +366,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis5595_adapter = { static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_SIS5595, .id = I2C_HW_SMBUS_SIS5595,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };

View File

@ -1,7 +1,4 @@
/* /*
i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -55,6 +52,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* SIS630 SMBus registers */ /* SIS630 SMBus registers */
@ -134,7 +132,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc
if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
return -1; return -EBUSY;
} else { } else {
dev_dbg(&adap->dev, "Successful!\n"); dev_dbg(&adap->dev, "Successful!\n");
} }
@ -177,17 +175,17 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n"); dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -1; result = -ETIMEDOUT;
} }
if (temp & 0x02) { if (temp & 0x02) {
dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
result = -1; result = -ENXIO;
} }
if (temp & 0x04) { if (temp & 0x04) {
dev_err(&adap->dev, "Bus collision!\n"); dev_err(&adap->dev, "Bus collision!\n");
result = -1; result = -EIO;
/* /*
TBD: Datasheet say: TBD: Datasheet say:
the software should clear this bit and restart SMBUS operation. the software should clear this bit and restart SMBUS operation.
@ -250,8 +248,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
if (i==8 || (len<8 && i==len)) { if (i==8 || (len<8 && i==len)) {
dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
/* first transaction */ /* first transaction */
if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) rc = sis630_transaction_start(adap,
return -1; SIS630_BLOCK_DATA, &oldclock);
if (rc)
return rc;
} }
else if ((i-1)%8 == 7 || i==len) { else if ((i-1)%8 == 7 || i==len) {
dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
@ -264,9 +264,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
*/ */
sis630_write(SMB_STS,0x10); sis630_write(SMB_STS,0x10);
} }
if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { rc = sis630_transaction_wait(adap,
SIS630_BLOCK_DATA);
if (rc) {
dev_dbg(&adap->dev, "trans_wait failed\n"); dev_dbg(&adap->dev, "trans_wait failed\n");
rc = -1;
break; break;
} }
} }
@ -275,13 +276,14 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
else { else {
/* read request */ /* read request */
data->block[0] = len = 0; data->block[0] = len = 0;
if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) { rc = sis630_transaction_start(adap,
return -1; SIS630_BLOCK_DATA, &oldclock);
} if (rc)
return rc;
do { do {
if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
if (rc) {
dev_dbg(&adap->dev, "trans_wait failed\n"); dev_dbg(&adap->dev, "trans_wait failed\n");
rc = -1;
break; break;
} }
/* if this first transaction then read byte count */ /* if this first transaction then read byte count */
@ -311,11 +313,13 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
return rc; return rc;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 sis630_access(struct i2c_adapter *adap, u16 addr, static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data) u8 command, int size, union i2c_smbus_data *data)
{ {
int status;
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
@ -350,13 +354,14 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
size = SIS630_BLOCK_DATA; size = SIS630_BLOCK_DATA;
return sis630_block_data(adap, data, read_write); return sis630_block_data(adap, data, read_write);
default: default:
printk("Unsupported I2C size\n"); dev_warn(&adap->dev, "Unsupported transaction %d\n",
return -1; size);
break; return -EOPNOTSUPP;
} }
if (sis630_transaction(adap, size)) status = sis630_transaction(adap, size);
return -1; if (status)
return status;
if ((size != SIS630_PCALL) && if ((size != SIS630_PCALL) &&
((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
@ -372,9 +377,6 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
case SIS630_WORD_DATA: case SIS630_WORD_DATA:
data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
break; break;
default:
return -1;
break;
} }
return 0; return 0;
@ -433,6 +435,11 @@ static int sis630_setup(struct pci_dev *sis630_dev)
dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name);
if (retval)
goto exit;
/* Everything is happy, let's grab the memory and set things up. */ /* Everything is happy, let's grab the memory and set things up. */
if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name)) { sis630_driver.name)) {
@ -458,7 +465,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis630_adapter = { static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_SIS630, .id = I2C_HW_SMBUS_SIS630,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };

View File

@ -1,7 +1,4 @@
/* /*
sis96x.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com> Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -40,6 +37,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* base address register in PCI config space */ /* base address register in PCI config space */
@ -111,7 +109,7 @@ static int sis96x_transaction(int size)
/* check it again */ /* check it again */
if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) { if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {
dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp); dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp);
return -1; return -EBUSY;
} else { } else {
dev_dbg(&sis96x_adapter.dev, "Successful\n"); dev_dbg(&sis96x_adapter.dev, "Successful\n");
} }
@ -136,19 +134,19 @@ static int sis96x_transaction(int size)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp); dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
result = -1; result = -ETIMEDOUT;
} }
/* device error - probably missing ACK */ /* device error - probably missing ACK */
if (temp & 0x02) { if (temp & 0x02) {
dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n"); dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n");
result = -1; result = -ENXIO;
} }
/* bus collision */ /* bus collision */
if (temp & 0x04) { if (temp & 0x04) {
dev_dbg(&sis96x_adapter.dev, "Bus collision!\n"); dev_dbg(&sis96x_adapter.dev, "Bus collision!\n");
result = -1; result = -EIO;
} }
/* Finish up by resetting the bus */ /* Finish up by resetting the bus */
@ -161,11 +159,12 @@ static int sis96x_transaction(int size)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 sis96x_access(struct i2c_adapter * adap, u16 addr, static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
{ {
int status;
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
@ -200,20 +199,14 @@ static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
SIS96x_PROC_CALL : SIS96x_WORD_DATA); SIS96x_PROC_CALL : SIS96x_WORD_DATA);
break; break;
case I2C_SMBUS_BLOCK_DATA:
/* TO DO: */
dev_info(&adap->dev, "SMBus block not implemented!\n");
return -1;
break;
default: default:
dev_info(&adap->dev, "Unsupported I2C size\n"); dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
break;
} }
if (sis96x_transaction(size)) status = sis96x_transaction(size);
return -1; if (status)
return status;
if ((size != SIS96x_PROC_CALL) && if ((size != SIS96x_PROC_CALL) &&
((read_write == I2C_SMBUS_WRITE) || (size == SIS96x_QUICK))) ((read_write == I2C_SMBUS_WRITE) || (size == SIS96x_QUICK)))
@ -249,7 +242,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis96x_adapter = { static struct i2c_adapter sis96x_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_SIS96X, .id = I2C_HW_SMBUS_SIS96X,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
@ -286,6 +279,10 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
dev_info(&dev->dev, "SiS96x SMBus base address: 0x%04x\n", dev_info(&dev->dev, "SiS96x SMBus base address: 0x%04x\n",
sis96x_smbus_base); sis96x_smbus_base);
retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]);
if (retval)
return retval;
/* Everything is happy, let's grab the memory and set things up. */ /* Everything is happy, let's grab the memory and set things up. */
if (!request_region(sis96x_smbus_base, SMB_IOSIZE, if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
sis96x_driver.name)) { sis96x_driver.name)) {

View File

@ -43,7 +43,7 @@ struct stub_chip {
static struct stub_chip *stub_chips; static struct stub_chip *stub_chips;
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
char read_write, u8 command, int size, union i2c_smbus_data * data) char read_write, u8 command, int size, union i2c_smbus_data * data)
{ {
@ -120,7 +120,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
default: default:
dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
ret = -1; ret = -EOPNOTSUPP;
break; break;
} /* switch (size) */ } /* switch (size) */
@ -140,7 +140,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter stub_adapter = { static struct i2c_adapter stub_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
.name = "SMBus stub driver", .name = "SMBus stub driver",
}; };

View File

@ -96,9 +96,8 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
sprintf(p, "$%02X", command); sprintf(p, "$%02X", command);
break; break;
default: default:
dev_dbg(&adapter->dev, "Unsupported transaction size %d\n", dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
size); return -EOPNOTSUPP;
return -EINVAL;
} }
/* Send the transaction to the TAOS EVM */ /* Send the transaction to the TAOS EVM */

View File

@ -1,7 +1,4 @@
/* /*
i2c-via.c - Part of lm_sensors, Linux kernel modules
for hardware monitoring
i2c Support for Via Technologies 82C586B South Bridge i2c Support for Via Technologies 82C586B South Bridge
Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
@ -87,7 +84,7 @@ static struct i2c_algo_bit_data bit_data = {
static struct i2c_adapter vt586b_adapter = { static struct i2c_adapter vt586b_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_B_VIA, .id = I2C_HW_B_VIA,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.name = "VIA i2c", .name = "VIA i2c",
.algo_data = &bit_data, .algo_data = &bit_data,
}; };

View File

@ -1,6 +1,4 @@
/* /*
i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com> Mark D. Studebaker <mdsxyz123@yahoo.com>
@ -50,6 +48,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
static struct pci_dev *vt596_pdev; static struct pci_dev *vt596_pdev;
@ -152,7 +151,7 @@ static int vt596_transaction(u8 size)
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_err(&vt596_adapter.dev, "SMBus reset failed! " dev_err(&vt596_adapter.dev, "SMBus reset failed! "
"(0x%02x)\n", temp); "(0x%02x)\n", temp);
return -1; return -EBUSY;
} }
} }
@ -167,24 +166,24 @@ static int vt596_transaction(u8 size)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -ETIMEDOUT;
dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
} }
if (temp & 0x10) { if (temp & 0x10) {
result = -1; result = -EIO;
dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n", dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
size); size);
} }
if (temp & 0x08) { if (temp & 0x08) {
result = -1; result = -EIO;
dev_err(&vt596_adapter.dev, "SMBus collision!\n"); dev_err(&vt596_adapter.dev, "SMBus collision!\n");
} }
if (temp & 0x04) { if (temp & 0x04) {
int read = inb_p(SMBHSTADD) & 0x01; int read = inb_p(SMBHSTADD) & 0x01;
result = -1; result = -ENXIO;
/* The quick and receive byte commands are used to probe /* The quick and receive byte commands are used to probe
for chips, so errors are expected, and we don't want for chips, so errors are expected, and we don't want
to frighten the user. */ to frighten the user. */
@ -202,12 +201,13 @@ static int vt596_transaction(u8 size)
return result; return result;
} }
/* Return -1 on error, 0 on success */ /* Return negative errno on error, 0 on success */
static s32 vt596_access(struct i2c_adapter *adap, u16 addr, static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data) int size, union i2c_smbus_data *data)
{ {
int i; int i;
int status;
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
@ -258,8 +258,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD); outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
if (vt596_transaction(size)) /* Error in transaction */ status = vt596_transaction(size);
return -1; if (status)
return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
return 0; return 0;
@ -285,9 +286,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
return 0; return 0;
exit_unsupported: exit_unsupported:
dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n", dev_warn(&vt596_adapter.dev, "Unsupported transaction %d\n",
size); size);
return -1; return -EOPNOTSUPP;
} }
static u32 vt596_func(struct i2c_adapter *adapter) static u32 vt596_func(struct i2c_adapter *adapter)
@ -309,7 +310,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter vt596_adapter = { static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_VIA2, .id = I2C_HW_SMBUS_VIA2,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
@ -354,6 +355,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
} }
found: found:
error = acpi_check_region(vt596_smba, 8, vt596_driver.name);
if (error)
return error;
if (!request_region(vt596_smba, 8, vt596_driver.name)) { if (!request_region(vt596_smba, 8, vt596_driver.name)) {
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
vt596_smba); vt596_smba);

View File

@ -1,6 +1,4 @@
/* /*
voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>, Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Philip Edelbrock <phil@netroedge.com>,
Ralph Metzler <rjkm@thp.uni-koeln.de>, and Ralph Metzler <rjkm@thp.uni-koeln.de>, and

View File

@ -442,7 +442,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
adapter->owner = THIS_MODULE; adapter->owner = THIS_MODULE;
adapter->id = I2C_HW_SMBUS_SCX200; adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm; adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adapter->dev.parent = dev; adapter->dev.parent = dev;
mutex_init(&iface->mutex); mutex_init(&iface->mutex);

View File

@ -14,6 +14,32 @@ config DS1682
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called ds1682. will be called ds1682.
config AT24
tristate "EEPROMs from most vendors"
depends on SYSFS && EXPERIMENTAL
help
Enable this driver to get read/write support to most I2C EEPROMs,
after you configure the driver to know about each EEPROM on
your target board. Use these generic chip names, instead of
vendor-specific ones like at24c64 or 24lc02:
24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
Unless you like data loss puzzles, always be sure that any chip
you configure as a 24c32 (32 kbit) or larger is NOT really a
24c16 (16 kbit) or smaller, and vice versa. Marking the chip
as read-only won't help recover from this. Also, if your chip
has any software write-protect mechanism you may want to review the
code to make sure this driver won't turn it on by accident.
If you use this with an SMBus adapter instead of an I2C adapter,
full functionality is not available. Only smaller devices are
supported (24c16 and below, max 4 kByte).
This driver can also be built as a module. If so, the module
will be called at24.
config SENSORS_EEPROM config SENSORS_EEPROM
tristate "EEPROM reader" tristate "EEPROM reader"
depends on EXPERIMENTAL depends on EXPERIMENTAL
@ -26,8 +52,8 @@ config SENSORS_EEPROM
will be called eeprom. will be called eeprom.
config SENSORS_PCF8574 config SENSORS_PCF8574
tristate "Philips PCF8574 and PCF8574A" tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
depends on EXPERIMENTAL depends on EXPERIMENTAL && GPIO_PCF857X = "n"
default n default n
help help
If you say yes here you get support for Philips PCF8574 and If you say yes here you get support for Philips PCF8574 and
@ -36,12 +62,16 @@ config SENSORS_PCF8574
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called pcf8574. will be called pcf8574.
This driver is deprecated and will be dropped soon. Use
drivers/gpio/pcf857x.c instead.
These devices are hard to detect and rarely found on mainstream These devices are hard to detect and rarely found on mainstream
hardware. If unsure, say N. hardware. If unsure, say N.
config PCF8575 config PCF8575
tristate "Philips PCF8575" tristate "Philips PCF8575 (DEPRECATED)"
default n default n
depends on GPIO_PCF857X = "n"
help help
If you say yes here you get support for Philips PCF8575 chip. If you say yes here you get support for Philips PCF8575 chip.
This chip is a 16-bit I/O expander for the I2C bus. Several other This chip is a 16-bit I/O expander for the I2C bus. Several other
@ -50,12 +80,15 @@ config PCF8575
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called pcf8575. will be called pcf8575.
This driver is deprecated and will be dropped soon. Use
drivers/gpio/pcf857x.c instead.
This device is hard to detect and is rarely found on mainstream This device is hard to detect and is rarely found on mainstream
hardware. If unsure, say N. hardware. If unsure, say N.
config SENSORS_PCA9539 config SENSORS_PCA9539
tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)" tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)"
depends on EXPERIMENTAL && GPIO_PCA9539 = "n" depends on EXPERIMENTAL && GPIO_PCA953X = "n"
help help
If you say yes here you get support for the Philips PCA9539 If you say yes here you get support for the Philips PCA9539
16-bit I/O port. 16-bit I/O port.
@ -64,7 +97,7 @@ config SENSORS_PCA9539
will be called pca9539. will be called pca9539.
This driver is deprecated and will be dropped soon. Use This driver is deprecated and will be dropped soon. Use
drivers/gpio/pca9539.c instead. drivers/gpio/pca953x.c instead.
config SENSORS_PCF8591 config SENSORS_PCF8591
tristate "Philips PCF8591" tristate "Philips PCF8591"

View File

@ -10,6 +10,7 @@
# #
obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_DS1682) += ds1682.o
obj-$(CONFIG_AT24) += at24.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o

583
drivers/i2c/chips/at24.c Normal file
View File

@ -0,0 +1,583 @@
/*
* at24.c - handle most I2C EEPROMs
*
* Copyright (C) 2005-2007 David Brownell
* Copyright (C) 2008 Wolfram Sang, Pengutronix
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/mod_devicetable.h>
#include <linux/log2.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c/at24.h>
/*
* I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
* Differences between different vendor product lines (like Atmel AT24C or
* MicroChip 24LC, etc) won't much matter for typical read/write access.
* There are also I2C RAM chips, likewise interchangeable. One example
* would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes).
*
* However, misconfiguration can lose data. "Set 16-bit memory address"
* to a part with 8-bit addressing will overwrite data. Writing with too
* big a page size also loses data. And it's not safe to assume that the
* conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC
* uses 0x51, for just one example.
*
* Accordingly, explicit board-specific configuration data should be used
* in almost all cases. (One partial exception is an SMBus used to access
* "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.)
*
* So this driver uses "new style" I2C driver binding, expecting to be
* told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
* similar kernel-resident tables; or, configuration data coming from
* a bootloader.
*
* Other than binding model, current differences from "eeprom" driver are
* that this one handles write access and isn't restricted to 24c02 devices.
* It also handles larger devices (32 kbit and up) with two-byte addresses,
* which won't work on pure SMBus systems.
*/
struct at24_data {
struct at24_platform_data chip;
bool use_smbus;
/*
* Lock protects against activities from other Linux tasks,
* but not from changes by other I2C masters.
*/
struct mutex lock;
struct bin_attribute bin;
u8 *writebuf;
unsigned write_max;
unsigned num_addresses;
/*
* Some chips tie up multiple I2C addresses; dummy devices reserve
* them for us, and we'll use them with SMBus calls.
*/
struct i2c_client *client[];
};
/*
* This parameter is to help this driver avoid blocking other drivers out
* of I2C for potentially troublesome amounts of time. With a 100 kHz I2C
* clock, one 256 byte read takes about 1/43 second which is excessive;
* but the 1/170 second it takes at 400 kHz may be quite reasonable; and
* at 1 MHz (Fm+) a 1/430 second delay could easily be invisible.
*
* This value is forced to be a power of two so that writes align on pages.
*/
static unsigned io_limit = 128;
module_param(io_limit, uint, 0);
MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)");
/*
* Specs often allow 5 msec for a page write, sometimes 20 msec;
* it's important to recover from write timeouts.
*/
static unsigned write_timeout = 25;
module_param(write_timeout, uint, 0);
MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
#define AT24_SIZE_BYTELEN 5
#define AT24_SIZE_FLAGS 8
#define AT24_BITMASK(x) (BIT(x) - 1)
/* create non-zero magic value for given eeprom parameters */
#define AT24_DEVICE_MAGIC(_len, _flags) \
((1 << AT24_SIZE_FLAGS | (_flags)) \
<< AT24_SIZE_BYTELEN | ilog2(_len))
static const struct i2c_device_id at24_ids[] = {
/* needs 8 addresses as A0-A2 are ignored */
{ "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
/* old variants can't be handled with this generic entry! */
{ "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
{ "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
/* spd is a 24c02 in memory DIMMs */
{ "spd", AT24_DEVICE_MAGIC(2048 / 8,
AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
{ "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
/* 24rf08 quirk is handled at i2c-core */
{ "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },
{ "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },
{ "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },
{ "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },
{ "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },
{ "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },
{ "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },
{ "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) },
{ "at24", 0 },
{ /* END OF LIST */ }
};
MODULE_DEVICE_TABLE(i2c, at24_ids);
/*-------------------------------------------------------------------------*/
/*
* This routine supports chips which consume multiple I2C addresses. It
* computes the addressing information to be used for a given r/w request.
* Assumes that sanity checks for offset happened at sysfs-layer.
*/
static struct i2c_client *at24_translate_offset(struct at24_data *at24,
unsigned *offset)
{
unsigned i;
if (at24->chip.flags & AT24_FLAG_ADDR16) {
i = *offset >> 16;
*offset &= 0xffff;
} else {
i = *offset >> 8;
*offset &= 0xff;
}
return at24->client[i];
}
static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
unsigned offset, size_t count)
{
struct i2c_msg msg[2];
u8 msgbuf[2];
struct i2c_client *client;
int status, i;
memset(msg, 0, sizeof(msg));
/*
* REVISIT some multi-address chips don't rollover page reads to
* the next slave address, so we may need to truncate the count.
* Those chips might need another quirk flag.
*
* If the real hardware used four adjacent 24c02 chips and that
* were misconfigured as one 24c08, that would be a similar effect:
* one "eeprom" file not four, but larger reads would fail when
* they crossed certain pages.
*/
/*
* Slave address and byte offset derive from the offset. Always
* set the byte address; on a multi-master board, another master
* may have changed the chip's "current" address pointer.
*/
client = at24_translate_offset(at24, &offset);
if (count > io_limit)
count = io_limit;
/* Smaller eeproms can work given some SMBus extension calls */
if (at24->use_smbus) {
if (count > I2C_SMBUS_BLOCK_MAX)
count = I2C_SMBUS_BLOCK_MAX;
status = i2c_smbus_read_i2c_block_data(client, offset,
count, buf);
dev_dbg(&client->dev, "smbus read %zd@%d --> %d\n",
count, offset, status);
return (status < 0) ? -EIO : status;
}
/*
* When we have a better choice than SMBus calls, use a combined
* I2C message. Write address; then read up to io_limit data bytes.
* Note that read page rollover helps us here (unlike writes).
* msgbuf is u8 and will cast to our needs.
*/
i = 0;
if (at24->chip.flags & AT24_FLAG_ADDR16)
msgbuf[i++] = offset >> 8;
msgbuf[i++] = offset;
msg[0].addr = client->addr;
msg[0].buf = msgbuf;
msg[0].len = i;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].buf = buf;
msg[1].len = count;
status = i2c_transfer(client->adapter, msg, 2);
dev_dbg(&client->dev, "i2c read %zd@%d --> %d\n",
count, offset, status);
if (status == 2)
return count;
else if (status >= 0)
return -EIO;
else
return status;
}
static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct at24_data *at24;
ssize_t retval = 0;
at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
if (unlikely(!count))
return count;
/*
* Read data from chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
mutex_lock(&at24->lock);
while (count) {
ssize_t status;
status = at24_eeprom_read(at24, buf, off, count);
if (status <= 0) {
if (retval == 0)
retval = status;
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
mutex_unlock(&at24->lock);
return retval;
}
/*
* REVISIT: export at24_bin{read,write}() to let other kernel code use
* eeprom data. For example, it might hold a board's Ethernet address, or
* board-specific calibration data generated on the manufacturing floor.
*/
/*
* Note that if the hardware write-protect pin is pulled high, the whole
* chip is normally write protected. But there are plenty of product
* variants here, including OTP fuses and partial chip protect.
*
* We only use page mode writes; the alternative is sloooow. This routine
* writes at most one page.
*/
static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
unsigned offset, size_t count)
{
struct i2c_client *client;
struct i2c_msg msg;
ssize_t status;
unsigned long timeout, write_time;
unsigned next_page;
/* Get corresponding I2C address and adjust offset */
client = at24_translate_offset(at24, &offset);
/* write_max is at most a page */
if (count > at24->write_max)
count = at24->write_max;
/* Never roll over backwards, to the start of this page */
next_page = roundup(offset + 1, at24->chip.page_size);
if (offset + count > next_page)
count = next_page - offset;
/* If we'll use I2C calls for I/O, set up the message */
if (!at24->use_smbus) {
int i = 0;
msg.addr = client->addr;
msg.flags = 0;
/* msg.buf is u8 and casts will mask the values */
msg.buf = at24->writebuf;
if (at24->chip.flags & AT24_FLAG_ADDR16)
msg.buf[i++] = offset >> 8;
msg.buf[i++] = offset;
memcpy(&msg.buf[i], buf, count);
msg.len = i + count;
}
/*
* Writes fail if the previous one didn't complete yet. We may
* loop a few times until this one succeeds, waiting at least
* long enough for one entire page write to work.
*/
timeout = jiffies + msecs_to_jiffies(write_timeout);
do {
write_time = jiffies;
if (at24->use_smbus) {
status = i2c_smbus_write_i2c_block_data(client,
offset, count, buf);
if (status == 0)
status = count;
} else {
status = i2c_transfer(client->adapter, &msg, 1);
if (status == 1)
status = count;
}
dev_dbg(&client->dev, "write %zd@%d --> %zd (%ld)\n",
count, offset, status, jiffies);
if (status == count)
return count;
/* REVISIT: at HZ=100, this is sloooow */
msleep(1);
} while (time_before(write_time, timeout));
return -ETIMEDOUT;
}
static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct at24_data *at24;
ssize_t retval = 0;
at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
if (unlikely(!count))
return count;
/*
* Write data to chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
mutex_lock(&at24->lock);
while (count) {
ssize_t status;
status = at24_eeprom_write(at24, buf, off, count);
if (status <= 0) {
if (retval == 0)
retval = status;
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
mutex_unlock(&at24->lock);
return retval;
}
/*-------------------------------------------------------------------------*/
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct at24_platform_data chip;
bool writable;
bool use_smbus = false;
struct at24_data *at24;
int err;
unsigned i, num_addresses;
kernel_ulong_t magic;
if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data;
} else {
if (!id->driver_data) {
err = -ENODEV;
goto err_out;
}
magic = id->driver_data;
chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
magic >>= AT24_SIZE_BYTELEN;
chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
/*
* This is slow, but we can't know all eeproms, so we better
* play safe. Specifying custom eeprom-types via platform_data
* is recommended anyhow.
*/
chip.page_size = 1;
}
if (!is_power_of_2(chip.byte_len))
dev_warn(&client->dev,
"byte_len looks suspicious (no power of 2)!\n");
if (!is_power_of_2(chip.page_size))
dev_warn(&client->dev,
"page_size looks suspicious (no power of 2)!\n");
/* Use I2C operations unless we're stuck with SMBus extensions. */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
if (chip.flags & AT24_FLAG_ADDR16) {
err = -EPFNOSUPPORT;
goto err_out;
}
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
err = -EPFNOSUPPORT;
goto err_out;
}
use_smbus = true;
}
if (chip.flags & AT24_FLAG_TAKE8ADDR)
num_addresses = 8;
else
num_addresses = DIV_ROUND_UP(chip.byte_len,
(chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
at24 = kzalloc(sizeof(struct at24_data) +
num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
if (!at24) {
err = -ENOMEM;
goto err_out;
}
mutex_init(&at24->lock);
at24->use_smbus = use_smbus;
at24->chip = chip;
at24->num_addresses = num_addresses;
/*
* Export the EEPROM bytes through sysfs, since that's convenient.
* By default, only root should see the data (maybe passwords etc)
*/
at24->bin.attr.name = "eeprom";
at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
at24->bin.attr.owner = THIS_MODULE;
at24->bin.read = at24_bin_read;
at24->bin.size = chip.byte_len;
writable = !(chip.flags & AT24_FLAG_READONLY);
if (writable) {
if (!use_smbus || i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
unsigned write_max = chip.page_size;
at24->bin.write = at24_bin_write;
at24->bin.attr.mode |= S_IWUSR;
if (write_max > io_limit)
write_max = io_limit;
if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
write_max = I2C_SMBUS_BLOCK_MAX;
at24->write_max = write_max;
/* buffer (data + address at the beginning) */
at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL);
if (!at24->writebuf) {
err = -ENOMEM;
goto err_struct;
}
} else {
dev_warn(&client->dev,
"cannot write due to controller restrictions.");
}
}
at24->client[0] = client;
/* use dummy devices for multiple-address chips */
for (i = 1; i < num_addresses; i++) {
at24->client[i] = i2c_new_dummy(client->adapter,
client->addr + i);
if (!at24->client[i]) {
dev_err(&client->dev, "address 0x%02x unavailable\n",
client->addr + i);
err = -EADDRINUSE;
goto err_clients;
}
}
err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
if (err)
goto err_clients;
i2c_set_clientdata(client, at24);
dev_info(&client->dev, "%Zd byte %s EEPROM %s\n",
at24->bin.size, client->name,
writable ? "(writable)" : "(read-only)");
dev_dbg(&client->dev,
"page_size %d, num_addresses %d, write_max %d%s\n",
chip.page_size, num_addresses,
at24->write_max,
use_smbus ? ", use_smbus" : "");
return 0;
err_clients:
for (i = 1; i < num_addresses; i++)
if (at24->client[i])
i2c_unregister_device(at24->client[i]);
kfree(at24->writebuf);
err_struct:
kfree(at24);
err_out:
dev_dbg(&client->dev, "probe error %d\n", err);
return err;
}
static int __devexit at24_remove(struct i2c_client *client)
{
struct at24_data *at24;
int i;
at24 = i2c_get_clientdata(client);
sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
for (i = 1; i < at24->num_addresses; i++)
i2c_unregister_device(at24->client[i]);
kfree(at24->writebuf);
kfree(at24);
i2c_set_clientdata(client, NULL);
return 0;
}
/*-------------------------------------------------------------------------*/
static struct i2c_driver at24_driver = {
.driver = {
.name = "at24",
.owner = THIS_MODULE,
},
.probe = at24_probe,
.remove = __devexit_p(at24_remove),
.id_table = at24_ids,
};
static int __init at24_init(void)
{
io_limit = rounddown_pow_of_two(io_limit);
return i2c_add_driver(&at24_driver);
}
module_init(at24_init);
static void __exit at24_exit(void)
{
i2c_del_driver(&at24_driver);
}
module_exit(at24_exit);
MODULE_DESCRIPTION("Driver for most I2C EEPROMs");
MODULE_AUTHOR("David Brownell and Wolfram Sang");
MODULE_LICENSE("GPL");

View File

@ -1,15 +1,9 @@
/* /*
eeprom.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com> Philip Edelbrock <phil@netroedge.com>
Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
Copyright (C) 2003 IBM Corp. Copyright (C) 2003 IBM Corp.
Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
2004-01-16 Jean Delvare <khali@linux-fr.org>
Divide the eeprom in 32-byte (arbitrary) slices. This significantly
speeds sensors up, as well as various scripts using the eeprom
module.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -78,7 +72,7 @@ static struct i2c_driver eeprom_driver = {
static void eeprom_update_client(struct i2c_client *client, u8 slice) static void eeprom_update_client(struct i2c_client *client, u8 slice)
{ {
struct eeprom_data *data = i2c_get_clientdata(client); struct eeprom_data *data = i2c_get_clientdata(client);
int i, j; int i;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
@ -93,15 +87,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
!= 32) != 32)
goto exit; goto exit;
} else { } else {
if (i2c_smbus_write_byte(client, slice << 5)) { for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
dev_dbg(&client->dev, "eeprom read start has failed!\n"); int word = i2c_smbus_read_word_data(client, i);
goto exit; if (word < 0)
}
for (i = slice << 5; i < (slice + 1) << 5; i++) {
j = i2c_smbus_read_byte(client);
if (j < 0)
goto exit; goto exit;
data->data[i] = (u8) j; data->data[i] = word & 0xff;
data->data[i + 1] = word >> 8;
} }
} }
data->last_updated[slice] = jiffies; data->last_updated[slice] = jiffies;
@ -159,24 +150,33 @@ static struct bin_attribute eeprom_attr = {
static int eeprom_attach_adapter(struct i2c_adapter *adapter) static int eeprom_attach_adapter(struct i2c_adapter *adapter)
{ {
if (!(adapter->class & (I2C_CLASS_DDC | I2C_CLASS_SPD)))
return 0;
return i2c_probe(adapter, &addr_data, eeprom_detect); return i2c_probe(adapter, &addr_data, eeprom_detect);
} }
/* This function is called by i2c_probe */ /* This function is called by i2c_probe */
static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_client *client;
struct eeprom_data *data; struct eeprom_data *data;
int err = 0; int err = 0;
/* There are three ways we can read the EEPROM data: /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
addresses 0x50-0x57, but we only care about 0x50. So decline
attaching to addresses >= 0x51 on DDC buses */
if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51)
goto exit;
/* There are four ways we can read the EEPROM data:
(1) I2C block reads (faster, but unsupported by most adapters) (1) I2C block reads (faster, but unsupported by most adapters)
(2) Consecutive byte reads (100% overhead) (2) Word reads (128% overhead)
(3) Regular byte data reads (200% overhead) (3) Consecutive byte reads (88% overhead, unsafe)
The third method is not implemented by this driver because all (4) Regular byte data reads (265% overhead)
known adapters support at least the second. */ The third and fourth methods are not implemented by this driver
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA because all known adapters support one of the first two. */
| I2C_FUNC_SMBUS_BYTE)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
&& !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
goto exit; goto exit;
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
@ -184,50 +184,49 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit; goto exit;
} }
new_client = &data->client; client = &data->client;
memset(data->data, 0xff, EEPROM_SIZE); memset(data->data, 0xff, EEPROM_SIZE);
i2c_set_clientdata(new_client, data); i2c_set_clientdata(client, data);
new_client->addr = address; client->addr = address;
new_client->adapter = adapter; client->adapter = adapter;
new_client->driver = &eeprom_driver; client->driver = &eeprom_driver;
new_client->flags = 0;
/* Fill in the remaining client fields */ /* Fill in the remaining client fields */
strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); strlcpy(client->name, "eeprom", I2C_NAME_SIZE);
data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
data->nature = UNKNOWN; data->nature = UNKNOWN;
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(client)))
goto exit_kfree; goto exit_kfree;
/* Detect the Vaio nature of EEPROMs. /* Detect the Vaio nature of EEPROMs.
We use the "PCG-" or "VGN-" prefix as the signature. */ We use the "PCG-" or "VGN-" prefix as the signature. */
if (address == 0x57) { if (address == 0x57
&& i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
char name[4]; char name[4];
name[0] = i2c_smbus_read_byte_data(new_client, 0x80); name[0] = i2c_smbus_read_byte_data(client, 0x80);
name[1] = i2c_smbus_read_byte(new_client); name[1] = i2c_smbus_read_byte_data(client, 0x81);
name[2] = i2c_smbus_read_byte(new_client); name[2] = i2c_smbus_read_byte_data(client, 0x82);
name[3] = i2c_smbus_read_byte(new_client); name[3] = i2c_smbus_read_byte_data(client, 0x83);
if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
dev_info(&new_client->dev, "Vaio EEPROM detected, " dev_info(&client->dev, "Vaio EEPROM detected, "
"enabling privacy protection\n"); "enabling privacy protection\n");
data->nature = VAIO; data->nature = VAIO;
} }
} }
/* create the sysfs eeprom file */ /* create the sysfs eeprom file */
err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
if (err) if (err)
goto exit_detach; goto exit_detach;
return 0; return 0;
exit_detach: exit_detach:
i2c_detach_client(new_client); i2c_detach_client(client);
exit_kfree: exit_kfree:
kfree(data); kfree(data);
exit: exit:

View File

@ -170,7 +170,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *real_client; struct i2c_client *real_client;
struct i2c_client *fake_client; struct i2c_client *fake_client;
struct max6875_data *data; struct max6875_data *data;
int err = 0; int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
| I2C_FUNC_SMBUS_READ_BYTE)) | I2C_FUNC_SMBUS_READ_BYTE))
@ -195,7 +195,6 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
real_client->addr = address; real_client->addr = address;
real_client->adapter = adapter; real_client->adapter = adapter;
real_client->driver = &max6875_driver; real_client->driver = &max6875_driver;
real_client->flags = 0;
strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
@ -204,7 +203,6 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
fake_client->addr = address | 1; fake_client->addr = address | 1;
fake_client->adapter = adapter; fake_client->adapter = adapter;
fake_client->driver = &max6875_driver; fake_client->driver = &max6875_driver;
fake_client->flags = 0;
strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE); strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
if ((err = i2c_attach_client(real_client)) != 0) if ((err = i2c_attach_client(real_client)) != 0)

View File

@ -113,7 +113,7 @@ static int pca9539_attach_adapter(struct i2c_adapter *adapter)
/* This function is called by i2c_probe */ /* This function is called by i2c_probe */
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind) static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_client *client;
struct pca9539_data *data; struct pca9539_data *data;
int err = 0; int err = 0;
@ -127,29 +127,28 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit; goto exit;
} }
new_client = &data->client; client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(client, data);
new_client->addr = address; client->addr = address;
new_client->adapter = adapter; client->adapter = adapter;
new_client->driver = &pca9539_driver; client->driver = &pca9539_driver;
new_client->flags = 0;
if (kind < 0) { if (kind < 0) {
/* Detection: the pca9539 only has 8 registers (0-7). /* Detection: the pca9539 only has 8 registers (0-7).
A read of 7 should succeed, but a read of 8 should fail. */ A read of 7 should succeed, but a read of 8 should fail. */
if ((i2c_smbus_read_byte_data(new_client, 7) < 0) || if ((i2c_smbus_read_byte_data(client, 7) < 0) ||
(i2c_smbus_read_byte_data(new_client, 8) >= 0)) (i2c_smbus_read_byte_data(client, 8) >= 0))
goto exit_kfree; goto exit_kfree;
} }
strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE); strlcpy(client->name, "pca9539", I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(client)))
goto exit_kfree; goto exit_kfree;
/* Register sysfs hooks */ /* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj, err = sysfs_create_group(&client->dev.kobj,
&pca9539_defattr_group); &pca9539_defattr_group);
if (err) if (err)
goto exit_detach; goto exit_detach;
@ -157,7 +156,7 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
return 0; return 0;
exit_detach: exit_detach:
i2c_detach_client(new_client); i2c_detach_client(client);
exit_kfree: exit_kfree:
kfree(data); kfree(data);
exit: exit:

View File

@ -1,6 +1,4 @@
/* /*
pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Philip Edelbrock <phil@netroedge.com>,
Dan Eaton <dan.eaton@rocketlogix.com> Dan Eaton <dan.eaton@rocketlogix.com>
@ -129,7 +127,7 @@ static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
/* This function is called by i2c_probe */ /* This function is called by i2c_probe */
static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_client *client;
struct pcf8574_data *data; struct pcf8574_data *data;
int err = 0; int err = 0;
const char *client_name = ""; const char *client_name = "";
@ -144,12 +142,11 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit; goto exit;
} }
new_client = &data->client; client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(client, data);
new_client->addr = address; client->addr = address;
new_client->adapter = adapter; client->adapter = adapter;
new_client->driver = &pcf8574_driver; client->driver = &pcf8574_driver;
new_client->flags = 0;
/* Now, we would do the remaining detection. But the PCF8574 is plainly /* Now, we would do the remaining detection. But the PCF8574 is plainly
impossible to detect! Stupid chip. */ impossible to detect! Stupid chip. */
@ -168,23 +165,23 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
client_name = "pcf8574"; client_name = "pcf8574";
/* Fill in the remaining client fields and put it into the global list */ /* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, client_name, I2C_NAME_SIZE); strlcpy(client->name, client_name, I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(client)))
goto exit_free; goto exit_free;
/* Initialize the PCF8574 chip */ /* Initialize the PCF8574 chip */
pcf8574_init_client(new_client); pcf8574_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group); err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group);
if (err) if (err)
goto exit_detach; goto exit_detach;
return 0; return 0;
exit_detach: exit_detach:
i2c_detach_client(new_client); i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:

View File

@ -1,6 +1,4 @@
/* /*
pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net> Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
the help of Jean Delvare <khali@linux-fr.org> the help of Jean Delvare <khali@linux-fr.org>
@ -190,7 +188,7 @@ static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
/* This function is called by i2c_probe */ /* This function is called by i2c_probe */
static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_client *client;
struct pcf8591_data *data; struct pcf8591_data *data;
int err = 0; int err = 0;
@ -205,12 +203,11 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit; goto exit;
} }
new_client = &data->client; client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(client, data);
new_client->addr = address; client->addr = address;
new_client->adapter = adapter; client->adapter = adapter;
new_client->driver = &pcf8591_driver; client->driver = &pcf8591_driver;
new_client->flags = 0;
/* Now, we would do the remaining detection. But the PCF8591 is plainly /* Now, we would do the remaining detection. But the PCF8591 is plainly
impossible to detect! Stupid chip. */ impossible to detect! Stupid chip. */
@ -221,31 +218,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global /* Fill in the remaining client fields and put it into the global
list */ list */
strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); strlcpy(client->name, "pcf8591", I2C_NAME_SIZE);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(client)))
goto exit_kfree; goto exit_kfree;
/* Initialize the PCF8591 chip */ /* Initialize the PCF8591 chip */
pcf8591_init_client(new_client); pcf8591_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group); err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group);
if (err) if (err)
goto exit_detach; goto exit_detach;
/* Register input2 if not in "two differential inputs" mode */ /* Register input2 if not in "two differential inputs" mode */
if (input_mode != 3) { if (input_mode != 3) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&client->dev,
&dev_attr_in2_input))) &dev_attr_in2_input)))
goto exit_sysfs_remove; goto exit_sysfs_remove;
} }
/* Register input3 only in "four single ended inputs" mode */ /* Register input3 only in "four single ended inputs" mode */
if (input_mode == 0) { if (input_mode == 0) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&client->dev,
&dev_attr_in3_input))) &dev_attr_in3_input)))
goto exit_sysfs_remove; goto exit_sysfs_remove;
} }
@ -253,10 +250,10 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
return 0; return 0;
exit_sysfs_remove: exit_sysfs_remove:
sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
exit_detach: exit_detach:
i2c_detach_client(new_client); i2c_detach_client(client);
exit_kfree: exit_kfree:
kfree(data); kfree(data);
exit: exit:

View File

@ -29,13 +29,11 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/irqflags.h> #include <linux/irqflags.h>
#include <linux/semaphore.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "i2c-core.h" #include "i2c-core.h"
@ -44,7 +42,9 @@
static DEFINE_MUTEX(core_lock); static DEFINE_MUTEX(core_lock);
static DEFINE_IDR(i2c_adapter_idr); static DEFINE_IDR(i2c_adapter_idr);
#define is_newstyle_driver(d) ((d)->probe || (d)->remove) #define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -103,19 +103,14 @@ static int i2c_device_probe(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(dev->driver); struct i2c_driver *driver = to_i2c_driver(dev->driver);
const struct i2c_device_id *id;
int status; int status;
if (!driver->probe) if (!driver->probe || !driver->id_table)
return -ENODEV; return -ENODEV;
client->driver = driver; client->driver = driver;
dev_dbg(dev, "probe\n"); dev_dbg(dev, "probe\n");
if (driver->id_table) status = driver->probe(client, i2c_match_id(driver->id_table, client));
id = i2c_match_id(driver->id_table, client);
else
id = NULL;
status = driver->probe(client, id);
if (status) if (status)
client->driver = NULL; client->driver = NULL;
return status; return status;
@ -208,7 +203,7 @@ static struct device_attribute i2c_dev_attrs[] = {
{ }, { },
}; };
static struct bus_type i2c_bus_type = { struct bus_type i2c_bus_type = {
.name = "i2c", .name = "i2c",
.dev_attrs = i2c_dev_attrs, .dev_attrs = i2c_dev_attrs,
.match = i2c_device_match, .match = i2c_device_match,
@ -219,6 +214,7 @@ static struct bus_type i2c_bus_type = {
.suspend = i2c_device_suspend, .suspend = i2c_device_suspend,
.resume = i2c_device_resume, .resume = i2c_device_resume,
}; };
EXPORT_SYMBOL_GPL(i2c_bus_type);
/** /**
@ -306,6 +302,14 @@ void i2c_unregister_device(struct i2c_client *client)
return; return;
} }
if (adapter->client_unregister) {
if (adapter->client_unregister(client)) {
dev_warn(&client->dev,
"client_unregister [%s] failed\n",
client->name);
}
}
mutex_lock(&adapter->clist_lock); mutex_lock(&adapter->clist_lock);
list_del(&client->list); list_del(&client->list);
mutex_unlock(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
@ -416,6 +420,10 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data)
struct i2c_driver *driver = to_i2c_driver(d); struct i2c_driver *driver = to_i2c_driver(d);
struct i2c_adapter *adap = data; struct i2c_adapter *adap = data;
/* Detect supported devices on that bus, and instantiate them */
i2c_detect(adap, driver);
/* Let legacy drivers scan this bus for matching devices */
if (driver->attach_adapter) { if (driver->attach_adapter) {
/* We ignore the return code; if it fails, too bad */ /* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap); driver->attach_adapter(adap);
@ -455,7 +463,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
if (adap->nr < __i2c_first_dynamic_bus_num) if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap); i2c_scan_static_board_info(adap);
/* let legacy drivers scan this bus for matching devices */ /* Notify drivers */
dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
i2c_do_add_adapter); i2c_do_add_adapter);
@ -561,8 +569,19 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
{ {
struct i2c_driver *driver = to_i2c_driver(d); struct i2c_driver *driver = to_i2c_driver(d);
struct i2c_adapter *adapter = data; struct i2c_adapter *adapter = data;
struct i2c_client *client, *_n;
int res; int res;
/* Remove the devices we created ourselves */
list_for_each_entry_safe(client, _n, &driver->clients, detected) {
if (client->adapter == adapter) {
dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
client->name, client->addr);
list_del(&client->detected);
i2c_unregister_device(client);
}
}
if (!driver->detach_adapter) if (!driver->detach_adapter)
return 0; return 0;
res = driver->detach_adapter(adapter); res = driver->detach_adapter(adapter);
@ -582,8 +601,7 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
*/ */
int i2c_del_adapter(struct i2c_adapter *adap) int i2c_del_adapter(struct i2c_adapter *adap)
{ {
struct list_head *item, *_n; struct i2c_client *client, *_n;
struct i2c_client *client;
int res = 0; int res = 0;
mutex_lock(&core_lock); mutex_lock(&core_lock);
@ -604,10 +622,9 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because /* detach any active clients. This must be done first, because
* it can fail; in which case we give up. */ * it can fail; in which case we give up. */
list_for_each_safe(item, _n, &adap->clients) { list_for_each_entry_safe(client, _n, &adap->clients, list) {
struct i2c_driver *driver; struct i2c_driver *driver;
client = list_entry(item, struct i2c_client, list);
driver = client->driver; driver = client->driver;
/* new style, follow standard driver model */ /* new style, follow standard driver model */
@ -646,6 +663,20 @@ EXPORT_SYMBOL(i2c_del_adapter);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static int __attach_adapter(struct device *dev, void *data)
{
struct i2c_adapter *adapter = to_i2c_adapter(dev);
struct i2c_driver *driver = data;
i2c_detect(adapter, driver);
/* Legacy drivers scan i2c busses directly */
if (driver->attach_adapter)
driver->attach_adapter(adapter);
return 0;
}
/* /*
* An i2c_driver is used with one or more i2c_client (device) nodes to access * An i2c_driver is used with one or more i2c_client (device) nodes to access
* i2c slave chips, on a bus instance associated with some i2c_adapter. There * i2c slave chips, on a bus instance associated with some i2c_adapter. There
@ -685,23 +716,59 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
/* legacy drivers scan i2c busses directly */ INIT_LIST_HEAD(&driver->clients);
if (driver->attach_adapter) { /* Walk the adapters that are already present */
struct i2c_adapter *adapter; class_for_each_device(&i2c_adapter_class, driver, __attach_adapter);
down(&i2c_adapter_class.sem);
list_for_each_entry(adapter, &i2c_adapter_class.devices,
dev.node) {
driver->attach_adapter(adapter);
}
up(&i2c_adapter_class.sem);
}
mutex_unlock(&core_lock); mutex_unlock(&core_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(i2c_register_driver); EXPORT_SYMBOL(i2c_register_driver);
static int __detach_adapter(struct device *dev, void *data)
{
struct i2c_adapter *adapter = to_i2c_adapter(dev);
struct i2c_driver *driver = data;
struct i2c_client *client, *_n;
list_for_each_entry_safe(client, _n, &driver->clients, detected) {
dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
client->name, client->addr);
list_del(&client->detected);
i2c_unregister_device(client);
}
if (is_newstyle_driver(driver))
return 0;
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
* afterwards.
*/
if (driver->detach_adapter) {
if (driver->detach_adapter(adapter))
dev_err(&adapter->dev,
"detach_adapter failed for driver [%s]\n",
driver->driver.name);
} else {
struct i2c_client *client, *_n;
list_for_each_entry_safe(client, _n, &adapter->clients, list) {
if (client->driver != driver)
continue;
dev_dbg(&adapter->dev,
"detaching client [%s] at 0x%02x\n",
client->name, client->addr);
if (driver->detach_client(client))
dev_err(&adapter->dev, "detach_client "
"failed for client [%s] at 0x%02x\n",
client->name, client->addr);
}
}
return 0;
}
/** /**
* i2c_del_driver - unregister I2C driver * i2c_del_driver - unregister I2C driver
* @driver: the driver being unregistered * @driver: the driver being unregistered
@ -709,48 +776,10 @@ EXPORT_SYMBOL(i2c_register_driver);
*/ */
void i2c_del_driver(struct i2c_driver *driver) void i2c_del_driver(struct i2c_driver *driver)
{ {
struct list_head *item2, *_n;
struct i2c_client *client;
struct i2c_adapter *adap;
mutex_lock(&core_lock); mutex_lock(&core_lock);
/* new-style driver? */ class_for_each_device(&i2c_adapter_class, driver, __detach_adapter);
if (is_newstyle_driver(driver))
goto unregister;
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
* afterwards.
*/
down(&i2c_adapter_class.sem);
list_for_each_entry(adap, &i2c_adapter_class.devices, dev.node) {
if (driver->detach_adapter) {
if (driver->detach_adapter(adap)) {
dev_err(&adap->dev, "detach_adapter failed "
"for driver [%s]\n",
driver->driver.name);
}
} else {
list_for_each_safe(item2, _n, &adap->clients) {
client = list_entry(item2, struct i2c_client, list);
if (client->driver != driver)
continue;
dev_dbg(&adap->dev, "detaching client [%s] "
"at 0x%02x\n", client->name,
client->addr);
if (driver->detach_client(client)) {
dev_err(&adap->dev, "detach_client "
"failed for client [%s] at "
"0x%02x\n", client->name,
client->addr);
}
}
}
}
up(&i2c_adapter_class.sem);
unregister:
driver_unregister(&driver->driver); driver_unregister(&driver->driver);
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
@ -863,8 +892,9 @@ EXPORT_SYMBOL(i2c_detach_client);
*/ */
struct i2c_client *i2c_use_client(struct i2c_client *client) struct i2c_client *i2c_use_client(struct i2c_client *client)
{ {
get_device(&client->dev); if (client && get_device(&client->dev))
return client; return client;
return NULL;
} }
EXPORT_SYMBOL(i2c_use_client); EXPORT_SYMBOL(i2c_use_client);
@ -876,7 +906,8 @@ EXPORT_SYMBOL(i2c_use_client);
*/ */
void i2c_release_client(struct i2c_client *client) void i2c_release_client(struct i2c_client *client)
{ {
put_device(&client->dev); if (client)
put_device(&client->dev);
} }
EXPORT_SYMBOL(i2c_release_client); EXPORT_SYMBOL(i2c_release_client);
@ -942,10 +973,39 @@ module_exit(i2c_exit);
* ---------------------------------------------------- * ----------------------------------------------------
*/ */
/**
* i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to
* terminate the operation; each message begins with a START.
* @num: Number of messages to be executed.
*
* Returns negative errno, else the number of messages executed.
*
* Note that there is no requirement that each message be sent to
* the same slave address, although that is the most common model.
*/
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
{ {
int ret; int ret;
/* REVISIT the fault reporting model here is weak:
*
* - When we get an error after receiving N bytes from a slave,
* there is no way to report "N".
*
* - When we get a NAK after transmitting N bytes to a slave,
* there is no way to report "N" ... or to let the master
* continue executing the rest of this combined message, if
* that's the appropriate response.
*
* - When for example "num" is two and we successfully complete
* the first message but get an error part way through the
* second, it's unclear whether that should be reported as
* one (discarding status on the second message) or errno
* (discarding status on the first one).
*/
if (adap->algo->master_xfer) { if (adap->algo->master_xfer) {
#ifdef DEBUG #ifdef DEBUG
for (ret = 0; ret < num; ret++) { for (ret = 0; ret < num; ret++) {
@ -971,11 +1031,19 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
return ret; return ret;
} else { } else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n"); dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -ENOSYS; return -EOPNOTSUPP;
} }
} }
EXPORT_SYMBOL(i2c_transfer); EXPORT_SYMBOL(i2c_transfer);
/**
* i2c_master_send - issue a single I2C message in master transmit mode
* @client: Handle to slave device
* @buf: Data that will be written to the slave
* @count: How many bytes to write
*
* Returns negative errno, or else the number of bytes written.
*/
int i2c_master_send(struct i2c_client *client,const char *buf ,int count) int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
{ {
int ret; int ret;
@ -995,6 +1063,14 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
} }
EXPORT_SYMBOL(i2c_master_send); EXPORT_SYMBOL(i2c_master_send);
/**
* i2c_master_recv - issue a single I2C message in master receive mode
* @client: Handle to slave device
* @buf: Where to store data read from slave
* @count: How many bytes to read
*
* Returns negative errno, or else the number of bytes read.
*/
int i2c_master_recv(struct i2c_client *client, char *buf ,int count) int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
{ {
struct i2c_adapter *adap=client->adapter; struct i2c_adapter *adap=client->adapter;
@ -1103,7 +1179,7 @@ int i2c_probe(struct i2c_adapter *adapter,
dev_warn(&adapter->dev, "SMBus Quick command not supported, " dev_warn(&adapter->dev, "SMBus Quick command not supported, "
"can't probe for chips\n"); "can't probe for chips\n");
return -1; return -EOPNOTSUPP;
} }
/* Probe entries are done second, and are not affected by ignore /* Probe entries are done second, and are not affected by ignore
@ -1157,6 +1233,179 @@ int i2c_probe(struct i2c_adapter *adapter,
} }
EXPORT_SYMBOL(i2c_probe); EXPORT_SYMBOL(i2c_probe);
/* Separate detection function for new-style drivers */
static int i2c_detect_address(struct i2c_client *temp_client, int kind,
struct i2c_driver *driver)
{
struct i2c_board_info info;
struct i2c_adapter *adapter = temp_client->adapter;
int addr = temp_client->addr;
int err;
/* Make sure the address is valid */
if (addr < 0x03 || addr > 0x77) {
dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
addr);
return -EINVAL;
}
/* Skip if already in use */
if (i2c_check_addr(adapter, addr))
return 0;
/* Make sure there is something at this address, unless forced */
if (kind < 0) {
if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
I2C_SMBUS_QUICK, NULL) < 0)
return 0;
/* prevent 24RF08 corruption */
if ((addr & ~0x0f) == 0x50)
i2c_smbus_xfer(adapter, addr, 0, 0, 0,
I2C_SMBUS_QUICK, NULL);
}
/* Finally call the custom detection function */
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = addr;
err = driver->detect(temp_client, kind, &info);
if (err) {
/* -ENODEV is returned if the detection fails. We catch it
here as this isn't an error. */
return err == -ENODEV ? 0 : err;
}
/* Consistency check */
if (info.type[0] == '\0') {
dev_err(&adapter->dev, "%s detection function provided "
"no name for 0x%x\n", driver->driver.name,
addr);
} else {
struct i2c_client *client;
/* Detection succeeded, instantiate the device */
dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
info.type, info.addr);
client = i2c_new_device(adapter, &info);
if (client)
list_add_tail(&client->detected, &driver->clients);
else
dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
info.type, info.addr);
}
return 0;
}
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
{
const struct i2c_client_address_data *address_data;
struct i2c_client *temp_client;
int i, err = 0;
int adap_id = i2c_adapter_id(adapter);
address_data = driver->address_data;
if (!driver->detect || !address_data)
return 0;
/* Set up a temporary client to help detect callback */
temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!temp_client)
return -ENOMEM;
temp_client->adapter = adapter;
/* Force entries are done first, and are not affected by ignore
entries */
if (address_data->forces) {
const unsigned short * const *forces = address_data->forces;
int kind;
for (kind = 0; forces[kind]; kind++) {
for (i = 0; forces[kind][i] != I2C_CLIENT_END;
i += 2) {
if (forces[kind][i] == adap_id
|| forces[kind][i] == ANY_I2C_BUS) {
dev_dbg(&adapter->dev, "found force "
"parameter for adapter %d, "
"addr 0x%02x, kind %d\n",
adap_id, forces[kind][i + 1],
kind);
temp_client->addr = forces[kind][i + 1];
err = i2c_detect_address(temp_client,
kind, driver);
if (err)
goto exit_free;
}
}
}
}
/* Stop here if we can't use SMBUS_QUICK */
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
if (address_data->probe[0] == I2C_CLIENT_END
&& address_data->normal_i2c[0] == I2C_CLIENT_END)
goto exit_free;
dev_warn(&adapter->dev, "SMBus Quick command not supported, "
"can't probe for chips\n");
err = -EOPNOTSUPP;
goto exit_free;
}
/* Stop here if the classes do not match */
if (!(adapter->class & driver->class))
goto exit_free;
/* Probe entries are done second, and are not affected by ignore
entries either */
for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
if (address_data->probe[i] == adap_id
|| address_data->probe[i] == ANY_I2C_BUS) {
dev_dbg(&adapter->dev, "found probe parameter for "
"adapter %d, addr 0x%02x\n", adap_id,
address_data->probe[i + 1]);
temp_client->addr = address_data->probe[i + 1];
err = i2c_detect_address(temp_client, -1, driver);
if (err)
goto exit_free;
}
}
/* Normal entries are done last, unless shadowed by an ignore entry */
for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
int j, ignore;
ignore = 0;
for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
j += 2) {
if ((address_data->ignore[j] == adap_id ||
address_data->ignore[j] == ANY_I2C_BUS)
&& address_data->ignore[j + 1]
== address_data->normal_i2c[i]) {
dev_dbg(&adapter->dev, "found ignore "
"parameter for adapter %d, "
"addr 0x%02x\n", adap_id,
address_data->ignore[j + 1]);
ignore = 1;
break;
}
}
if (ignore)
continue;
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id,
address_data->normal_i2c[i]);
temp_client->addr = address_data->normal_i2c[i];
err = i2c_detect_address(temp_client, -1, driver);
if (err)
goto exit_free;
}
exit_free:
kfree(temp_client);
return err;
}
struct i2c_client * struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap, i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info, struct i2c_board_info *info,
@ -1295,29 +1544,38 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
if (rpec != cpec) { if (rpec != cpec) {
pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
rpec, cpec); rpec, cpec);
return -1; return -EBADMSG;
} }
return 0; return 0;
} }
s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value) /**
{ * i2c_smbus_read_byte - SMBus "receive byte" protocol
return i2c_smbus_xfer(client->adapter,client->addr,client->flags, * @client: Handle to slave device
value,0,I2C_SMBUS_QUICK,NULL); *
} * This executes the SMBus "receive byte" protocol, returning negative errno
EXPORT_SYMBOL(i2c_smbus_write_quick); * else the byte received from the device.
*/
s32 i2c_smbus_read_byte(struct i2c_client *client) s32 i2c_smbus_read_byte(struct i2c_client *client)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, int status;
I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
return -1; status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
else I2C_SMBUS_READ, 0,
return data.byte; I2C_SMBUS_BYTE, &data);
return (status < 0) ? status : data.byte;
} }
EXPORT_SYMBOL(i2c_smbus_read_byte); EXPORT_SYMBOL(i2c_smbus_read_byte);
/**
* i2c_smbus_write_byte - SMBus "send byte" protocol
* @client: Handle to slave device
* @value: Byte to be sent
*
* This executes the SMBus "send byte" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
{ {
return i2c_smbus_xfer(client->adapter,client->addr,client->flags, return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@ -1325,17 +1583,35 @@ s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
} }
EXPORT_SYMBOL(i2c_smbus_write_byte); EXPORT_SYMBOL(i2c_smbus_write_byte);
/**
* i2c_smbus_read_byte_data - SMBus "read byte" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
*
* This executes the SMBus "read byte" protocol, returning negative errno
* else a data byte received from the device.
*/
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, int status;
I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
return -1; status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
else I2C_SMBUS_READ, command,
return data.byte; I2C_SMBUS_BYTE_DATA, &data);
return (status < 0) ? status : data.byte;
} }
EXPORT_SYMBOL(i2c_smbus_read_byte_data); EXPORT_SYMBOL(i2c_smbus_read_byte_data);
/**
* i2c_smbus_write_byte_data - SMBus "write byte" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @value: Byte being written
*
* This executes the SMBus "write byte" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
@ -1346,17 +1622,35 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
} }
EXPORT_SYMBOL(i2c_smbus_write_byte_data); EXPORT_SYMBOL(i2c_smbus_write_byte_data);
/**
* i2c_smbus_read_word_data - SMBus "read word" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
*
* This executes the SMBus "read word" protocol, returning negative errno
* else a 16-bit unsigned "word" received from the device.
*/
s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, int status;
I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
return -1; status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
else I2C_SMBUS_READ, command,
return data.word; I2C_SMBUS_WORD_DATA, &data);
return (status < 0) ? status : data.word;
} }
EXPORT_SYMBOL(i2c_smbus_read_word_data); EXPORT_SYMBOL(i2c_smbus_read_word_data);
/**
* i2c_smbus_write_word_data - SMBus "write word" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @value: 16-bit "word" being written
*
* This executes the SMBus "write word" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
@ -1368,15 +1662,14 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
EXPORT_SYMBOL(i2c_smbus_write_word_data); EXPORT_SYMBOL(i2c_smbus_write_word_data);
/** /**
* i2c_smbus_read_block_data - SMBus block read request * i2c_smbus_read_block_data - SMBus "block read" protocol
* @client: Handle to slave device * @client: Handle to slave device
* @command: Command byte issued to let the slave know what data should * @command: Byte interpreted by slave
* be returned
* @values: Byte array into which data will be read; big enough to hold * @values: Byte array into which data will be read; big enough to hold
* the data returned by the slave. SMBus allows at most 32 bytes. * the data returned by the slave. SMBus allows at most 32 bytes.
* *
* Returns the number of bytes read in the slave's response, else a * This executes the SMBus "block read" protocol, returning negative errno
* negative number to indicate some kind of error. * else the number of data bytes in the slave's response.
* *
* Note that using this function requires that the client's adapter support * Note that using this function requires that the client's adapter support
* the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality. Not all adapter drivers * the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality. Not all adapter drivers
@ -1387,17 +1680,29 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
u8 *values) u8 *values)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int status;
if (i2c_smbus_xfer(client->adapter, client->addr, client->flags, status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_READ, command, I2C_SMBUS_READ, command,
I2C_SMBUS_BLOCK_DATA, &data)) I2C_SMBUS_BLOCK_DATA, &data);
return -1; if (status)
return status;
memcpy(values, &data.block[1], data.block[0]); memcpy(values, &data.block[1], data.block[0]);
return data.block[0]; return data.block[0];
} }
EXPORT_SYMBOL(i2c_smbus_read_block_data); EXPORT_SYMBOL(i2c_smbus_read_block_data);
/**
* i2c_smbus_write_block_data - SMBus "block write" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @length: Size of data block; SMBus allows at most 32 bytes
* @values: Byte array which will be written.
*
* This executes the SMBus "block write" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
u8 length, const u8 *values) u8 length, const u8 *values)
{ {
@ -1418,14 +1723,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
u8 length, u8 *values) u8 length, u8 *values)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int status;
if (length > I2C_SMBUS_BLOCK_MAX) if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX; length = I2C_SMBUS_BLOCK_MAX;
data.block[0] = length; data.block[0] = length;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_READ,command, I2C_SMBUS_READ, command,
I2C_SMBUS_I2C_BLOCK_DATA,&data)) I2C_SMBUS_I2C_BLOCK_DATA, &data);
return -1; if (status < 0)
return status;
memcpy(values, &data.block[1], data.block[0]); memcpy(values, &data.block[1], data.block[0]);
return data.block[0]; return data.block[0];
@ -1466,6 +1773,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
}; };
int i; int i;
u8 partial_pec = 0; u8 partial_pec = 0;
int status;
msgbuf0[0] = command; msgbuf0[0] = command;
switch(size) { switch(size) {
@ -1515,10 +1823,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
} else { } else {
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
dev_err(&adapter->dev, "smbus_access called with " dev_err(&adapter->dev,
"invalid block write size (%d)\n", "Invalid block write size %d\n",
data->block[0]); data->block[0]);
return -1; return -EINVAL;
} }
for (i = 1; i < msg[0].len; i++) for (i = 1; i < msg[0].len; i++)
msgbuf0[i] = data->block[i-1]; msgbuf0[i] = data->block[i-1];
@ -1528,10 +1836,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
num = 2; /* Another special case */ num = 2; /* Another special case */
read_write = I2C_SMBUS_READ; read_write = I2C_SMBUS_READ;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
dev_err(&adapter->dev, "%s called with invalid " dev_err(&adapter->dev,
"block proc call size (%d)\n", __func__, "Invalid block write size %d\n",
data->block[0]); data->block[0]);
return -1; return -EINVAL;
} }
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
for (i = 1; i < msg[0].len; i++) for (i = 1; i < msg[0].len; i++)
@ -1546,19 +1854,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
} else { } else {
msg[0].len = data->block[0] + 1; msg[0].len = data->block[0] + 1;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with " dev_err(&adapter->dev,
"invalid block write size (%d)\n", "Invalid block write size %d\n",
data->block[0]); data->block[0]);
return -1; return -EINVAL;
} }
for (i = 1; i <= data->block[0]; i++) for (i = 1; i <= data->block[0]; i++)
msgbuf0[i] = data->block[i]; msgbuf0[i] = data->block[i];
} }
break; break;
default: default:
dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n", dev_err(&adapter->dev, "Unsupported transaction %d\n", size);
size); return -EOPNOTSUPP;
return -1;
} }
i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
@ -1576,13 +1883,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
msg[num-1].len++; msg[num-1].len++;
} }
if (i2c_transfer(adapter, msg, num) < 0) status = i2c_transfer(adapter, msg, num);
return -1; if (status < 0)
return status;
/* Check PEC if last message is a read */ /* Check PEC if last message is a read */
if (i && (msg[num-1].flags & I2C_M_RD)) { if (i && (msg[num-1].flags & I2C_M_RD)) {
if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
return -1; if (status < 0)
return status;
} }
if (read_write == I2C_SMBUS_READ) if (read_write == I2C_SMBUS_READ)
@ -1610,9 +1919,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
return 0; return 0;
} }
/**
* i2c_smbus_xfer - execute SMBus protocol operations
* @adapter: Handle to I2C bus
* @addr: Address of SMBus slave on that bus
* @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)
* @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE
* @command: Byte interpreted by slave, for protocols which use such bytes
* @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL
* @data: Data to be read or written
*
* This executes an SMBus protocol operation, and returns a negative
* errno code else zero on success.
*/
s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
char read_write, u8 command, int size, char read_write, u8 command, int protocol,
union i2c_smbus_data * data) union i2c_smbus_data * data)
{ {
s32 res; s32 res;
@ -1622,11 +1943,11 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
if (adapter->algo->smbus_xfer) { if (adapter->algo->smbus_xfer) {
mutex_lock(&adapter->bus_lock); mutex_lock(&adapter->bus_lock);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
command,size,data); command, protocol, data);
mutex_unlock(&adapter->bus_lock); mutex_unlock(&adapter->bus_lock);
} else } else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data); command, protocol, data);
return res; return res;
} }

View File

@ -367,8 +367,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
return res; return res;
} }
static int i2cdev_ioctl(struct inode *inode, struct file *file, static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
struct i2c_client *client = (struct i2c_client *)file->private_data; struct i2c_client *client = (struct i2c_client *)file->private_data;
unsigned long funcs; unsigned long funcs;
@ -497,7 +496,7 @@ static const struct file_operations i2cdev_fops = {
.llseek = no_llseek, .llseek = no_llseek,
.read = i2cdev_read, .read = i2cdev_read,
.write = i2cdev_write, .write = i2cdev_write,
.ioctl = i2cdev_ioctl, .unlocked_ioctl = i2cdev_ioctl,
.open = i2cdev_open, .open = i2cdev_open,
.release = i2cdev_release, .release = i2cdev_release,
}; };
@ -559,19 +558,12 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
return 0; return 0;
} }
static int i2cdev_detach_client(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver i2cdev_driver = { static struct i2c_driver i2cdev_driver = {
.driver = { .driver = {
.name = "dev_driver", .name = "dev_driver",
}, },
.id = I2C_DRIVERID_I2CDEV,
.attach_adapter = i2cdev_attach_adapter, .attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter, .detach_adapter = i2cdev_detach_adapter,
.detach_client = i2cdev_detach_client,
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -106,6 +106,7 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
algo_data->setsda(algo_data->data, 1); algo_data->setsda(algo_data->data, 1);
algo_data->setscl(algo_data->data, 1); algo_data->setscl(algo_data->data, 1);
adapter->class |= I2C_CLASS_DDC;
return edid; return edid;
} }

View File

@ -100,7 +100,8 @@ static int intelfb_gpio_getsda(void *data)
static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
struct intelfb_i2c_chan *chan, struct intelfb_i2c_chan *chan,
const u32 reg, const char *name) const u32 reg, const char *name,
int class)
{ {
int rc; int rc;
@ -108,6 +109,7 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
chan->reg = reg; chan->reg = reg;
snprintf(chan->adapter.name, sizeof(chan->adapter.name), snprintf(chan->adapter.name, sizeof(chan->adapter.name),
"intelfb %s", name); "intelfb %s", name);
chan->adapter.class = class;
chan->adapter.owner = THIS_MODULE; chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_HW_B_INTELFB; chan->adapter.id = I2C_HW_B_INTELFB;
chan->adapter.algo_data = &chan->algo; chan->adapter.algo_data = &chan->algo;
@ -145,7 +147,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
/* setup the DDC bus for analog output */ /* setup the DDC bus for analog output */
intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
"CRTDDC_A"); "CRTDDC_A", I2C_CLASS_DDC);
i++; i++;
/* need to add the output busses for each device /* need to add the output busses for each device
@ -159,9 +161,9 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
case INTEL_865G: case INTEL_865G:
dinfo->output[i].type = INTELFB_OUTPUT_DVO; dinfo->output[i].type = INTELFB_OUTPUT_DVO;
intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
GPIOD, "DVODDC_D"); GPIOD, "DVODDC_D", I2C_CLASS_DDC);
intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
GPIOE, "DVOI2C_E"); GPIOE, "DVOI2C_E", 0);
i++; i++;
break; break;
case INTEL_915G: case INTEL_915G:
@ -174,7 +176,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
/* SDVO ports have a single control bus - 2 devices */ /* SDVO ports have a single control bus - 2 devices */
dinfo->output[i].type = INTELFB_OUTPUT_SDVO; dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
GPIOE, "SDVOCTRL_E"); GPIOE, "SDVOCTRL_E", 0);
/* TODO: initialize the SDVO */ /* TODO: initialize the SDVO */
/* I830SDVOInit(pScrn, i, DVOB); */ /* I830SDVOInit(pScrn, i, DVOB); */
i++; i++;

View File

@ -104,7 +104,9 @@ static struct i2c_algo_bit_data matrox_i2c_algo_template =
}; };
static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
unsigned int data, unsigned int clock, const char* name) { unsigned int data, unsigned int clock, const char *name,
int class)
{
int err; int err;
b->minfo = minfo; b->minfo = minfo;
@ -114,6 +116,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
snprintf(b->adapter.name, sizeof(b->adapter.name), name, snprintf(b->adapter.name, sizeof(b->adapter.name), name,
minfo->fbcon.node); minfo->fbcon.node);
i2c_set_adapdata(&b->adapter, b); i2c_set_adapdata(&b->adapter, b);
b->adapter.class = class;
b->adapter.algo_data = &b->bac; b->adapter.algo_data = &b->bac;
b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev; b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev;
b->bac = matrox_i2c_algo_template; b->bac = matrox_i2c_algo_template;
@ -159,22 +162,29 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
switch (ACCESS_FBINFO(chip)) { switch (ACCESS_FBINFO(chip)) {
case MGA_2064: case MGA_2064:
case MGA_2164: case MGA_2164:
err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0"); err = i2c_bus_reg(&m2info->ddc1, minfo,
DDC1B_DATA, DDC1B_CLK,
"DDC:fb%u #0", I2C_CLASS_DDC);
break; break;
default: default:
err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0"); err = i2c_bus_reg(&m2info->ddc1, minfo,
DDC1_DATA, DDC1_CLK,
"DDC:fb%u #0", I2C_CLASS_DDC);
break; break;
} }
if (err) if (err)
goto fail_ddc1; goto fail_ddc1;
if (ACCESS_FBINFO(devflags.dualhead)) { if (ACCESS_FBINFO(devflags.dualhead)) {
err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1"); err = i2c_bus_reg(&m2info->ddc2, minfo,
DDC2_DATA, DDC2_CLK,
"DDC:fb%u #1", I2C_CLASS_DDC);
if (err == -ENODEV) { if (err == -ENODEV) {
printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n"); printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
} else if (err) } else if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n"); printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
/* Register maven bus even on G450/G550 */ /* Register maven bus even on G450/G550 */
err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u"); err = i2c_bus_reg(&m2info->maven, minfo,
MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
if (err) if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
} }

View File

@ -33,9 +33,11 @@ struct i2c_algo_pcf_data {
int (*getclock) (void *data); int (*getclock) (void *data);
void (*waitforpin) (void); void (*waitforpin) (void);
/* local settings */ /* Multi-master lost arbitration back-off delay (msecs)
int udelay; * This should be set by the bus adapter or knowledgable client
int timeout; * if bus is multi-mastered, else zero
*/
unsigned long lab_mdelay;
}; };
int i2c_pcf_add_bus(struct i2c_adapter *); int i2c_pcf_add_bus(struct i2c_adapter *);

View File

@ -91,8 +91,6 @@
#define I2C_DRIVERID_M52790 95 /* Mitsubishi M52790SP/FP AV switch */ #define I2C_DRIVERID_M52790 95 /* Mitsubishi M52790SP/FP AV switch */
#define I2C_DRIVERID_CS5345 96 /* cs5345 audio processor */ #define I2C_DRIVERID_CS5345 96 /* cs5345 audio processor */
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */ #define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */
/* /*
@ -111,7 +109,6 @@
#define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */
#define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */
#define I2C_HW_B_S3VIA 0x010018 /* S3Via ProSavage adapter */
#define I2C_HW_B_ZR36067 0x010019 /* Zoran-36057/36067 based boards */ #define I2C_HW_B_ZR36067 0x010019 /* Zoran-36057/36067 based boards */
#define I2C_HW_B_PCILYNX 0x01001a /* TI PCILynx I2C adapter */ #define I2C_HW_B_PCILYNX 0x01001a /* TI PCILynx I2C adapter */
#define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */ #define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */

View File

@ -35,6 +35,8 @@
#include <linux/sched.h> /* for completion */ #include <linux/sched.h> /* for completion */
#include <linux/mutex.h> #include <linux/mutex.h>
extern struct bus_type i2c_bus_type;
/* --- General options ------------------------------------------------ */ /* --- General options ------------------------------------------------ */
struct i2c_msg; struct i2c_msg;
@ -43,6 +45,7 @@ struct i2c_adapter;
struct i2c_client; struct i2c_client;
struct i2c_driver; struct i2c_driver;
union i2c_smbus_data; union i2c_smbus_data;
struct i2c_board_info;
/* /*
* The master routines are the ones normally used to transmit data to devices * The master routines are the ones normally used to transmit data to devices
@ -69,9 +72,8 @@ extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
union i2c_smbus_data * data); union i2c_smbus_data * data);
/* Now follow the 'nice' access routines. These also document the calling /* Now follow the 'nice' access routines. These also document the calling
conventions of smbus_access. */ conventions of i2c_smbus_xfer. */
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte(struct i2c_client * client); extern s32 i2c_smbus_read_byte(struct i2c_client * client);
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value); extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@ -93,15 +95,33 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
u8 command, u8 length, u8 command, u8 length,
const u8 *values); const u8 *values);
/* /**
* A driver is capable of handling one or more physical devices present on * struct i2c_driver - represent an I2C device driver
* I2C adapters. This information is used to inform the driver of adapter * @class: What kind of i2c device we instantiate (for detect)
* events. * @detect: Callback for device detection
* @address_data: The I2C addresses to probe, ignore or force (for detect)
* @clients: List of detected clients we created (for i2c-core use only)
* *
* The driver.owner field should be set to the module owner of this driver. * The driver.owner field should be set to the module owner of this driver.
* The driver.name field should be set to the name of this driver. * The driver.name field should be set to the name of this driver.
*
* For automatic device detection, both @detect and @address_data must
* be defined. @class should also be set, otherwise only devices forced
* with module parameters will be created. The detect function must
* fill at least the name field of the i2c_board_info structure it is
* handed upon successful detection, and possibly also the flags field.
*
* If @detect is missing, the driver will still work fine for enumerated
* devices. Detected devices simply won't be supported. This is expected
* for the many I2C/SMBus devices which can't be detected reliably, and
* the ones which can always be enumerated in practice.
*
* The i2c_client structure which is handed to the @detect callback is
* not a real i2c_client. It is initialized just enough so that you can
* call i2c_smbus_read_byte_data and friends on it. Don't do anything
* else with it. In particular, calling dev_dbg and friends on it is
* not allowed.
*/ */
struct i2c_driver { struct i2c_driver {
int id; int id;
unsigned int class; unsigned int class;
@ -141,6 +161,11 @@ struct i2c_driver {
struct device_driver driver; struct device_driver driver;
const struct i2c_device_id *id_table; const struct i2c_device_id *id_table;
/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *);
const struct i2c_client_address_data *address_data;
struct list_head clients;
}; };
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
@ -156,6 +181,7 @@ struct i2c_driver {
* @dev: Driver model device node for the slave. * @dev: Driver model device node for the slave.
* @irq: indicates the IRQ generated by this device (if any) * @irq: indicates the IRQ generated by this device (if any)
* @list: list of active/busy clients (DEPRECATED) * @list: list of active/busy clients (DEPRECATED)
* @detected: member of an i2c_driver.clients list
* @released: used to synchronize client releases & detaches and references * @released: used to synchronize client releases & detaches and references
* *
* An i2c_client identifies a single device (i.e. chip) connected to an * An i2c_client identifies a single device (i.e. chip) connected to an
@ -173,6 +199,7 @@ struct i2c_client {
struct device dev; /* the device structure */ struct device dev; /* the device structure */
int irq; /* irq issued by device */ int irq; /* irq issued by device */
struct list_head list; /* DEPRECATED */ struct list_head list; /* DEPRECATED */
struct list_head detected;
struct completion released; struct completion released;
}; };
#define to_i2c_client(d) container_of(d, struct i2c_client, dev) #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@ -350,10 +377,11 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
#define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */
#define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */ #define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
#define I2C_CLASS_TV_DIGITAL (1<<2) /* dvb cards */ #define I2C_CLASS_TV_DIGITAL (1<<2) /* dvb cards */
#define I2C_CLASS_DDC (1<<3) /* i2c-matroxfb ? */ #define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */
#define I2C_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */ #define I2C_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */
#define I2C_CLASS_CAM_DIGITAL (1<<5) /* most webcams */ #define I2C_CLASS_CAM_DIGITAL (1<<5) /* most webcams */
#define I2C_CLASS_SOUND (1<<6) /* sound devices */ #define I2C_CLASS_SOUND (1<<6) /* sound devices */
#define I2C_CLASS_SPD (1<<7) /* SPD EEPROMs and similar */
#define I2C_CLASS_ALL (UINT_MAX) /* all of the above */ #define I2C_CLASS_ALL (UINT_MAX) /* all of the above */
/* i2c_client_address_data is the struct for holding default client /* i2c_client_address_data is the struct for holding default client
@ -537,7 +565,7 @@ union i2c_smbus_data {
/* and one more for user-space compatibility */ /* and one more for user-space compatibility */
}; };
/* smbus_access read or write markers */ /* i2c_smbus_xfer read or write markers */
#define I2C_SMBUS_READ 1 #define I2C_SMBUS_READ 1
#define I2C_SMBUS_WRITE 0 #define I2C_SMBUS_WRITE 0

28
include/linux/i2c/at24.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef _LINUX_AT24_H
#define _LINUX_AT24_H
#include <linux/types.h>
/*
* As seen through Linux I2C, differences between the most common types of I2C
* memory include:
* - How much memory is available (usually specified in bit)?
* - What write page size does it support?
* - Special flags (16 bit addresses, read_only, world readable...)?
*
* If you set up a custom eeprom type, please double-check the parameters.
* Especially page_size needs extra care, as you risk data loss if your value
* is bigger than what the chip actually supports!
*/
struct at24_platform_data {
u32 byte_len; /* size (sum of all addr) */
u16 page_size; /* for writes */
u8 flags;
#define AT24_FLAG_ADDR16 0x80 /* address pointer is 16 bit */
#define AT24_FLAG_READONLY 0x40 /* sysfs-entry will be read-only */
#define AT24_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */
#define AT24_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */
};
#endif /* _LINUX_AT24_H */