summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-06-26 13:13:26 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2008-06-26 13:13:26 +1000
commit7ba8504aac82074cd95e6a24c834c79a49b54471 (patch)
treefa705e5cf01fa5578ecb62af0726c4425b6738f5
parent6d8b51c03ed317c2bea2f133e9685643fba3575e (diff)
parent736a029c0fd8dcc447cd2391f8fbad6bcb719045 (diff)
Merge branch 'quilt/i2c'
Conflicts: drivers/i2c/i2c-core.c
-rw-r--r--Documentation/feature-removal-schedule.txt7
-rw-r--r--Documentation/i2c/busses/i2c-i81047
-rw-r--r--Documentation/i2c/busses/i2c-prosavage23
-rw-r--r--Documentation/i2c/busses/i2c-savage426
-rw-r--r--Documentation/i2c/chips/max68752
-rw-r--r--Documentation/i2c/chips/pca953910
-rw-r--r--Documentation/i2c/chips/pcf857412
-rw-r--r--Documentation/i2c/chips/pcf85759
-rw-r--r--Documentation/i2c/fault-codes127
-rw-r--r--Documentation/i2c/smbus-protocol4
-rw-r--r--Documentation/i2c/writing-clients69
-rw-r--r--MAINTAINERS7
-rw-r--r--arch/arm/mach-omap1/board-h3.c4
-rw-r--r--arch/arm/mach-omap2/board-h4.c11
-rw-r--r--arch/mips/sibyte/swarm/Makefile1
-rw-r--r--arch/mips/sibyte/swarm/swarm-i2c.c37
-rw-r--r--drivers/hwmon/adm1025.c100
-rw-r--r--drivers/hwmon/f75375s.c89
-rw-r--r--drivers/hwmon/lm63.c99
-rw-r--r--drivers/hwmon/lm77.c101
-rw-r--r--drivers/hwmon/lm80.c93
-rw-r--r--drivers/hwmon/lm83.c104
-rw-r--r--drivers/hwmon/lm92.c97
-rw-r--r--drivers/hwmon/lm93.c125
-rw-r--r--drivers/hwmon/max1619.c100
-rw-r--r--drivers/hwmon/max6650.c101
-rw-r--r--drivers/hwmon/smsc47m192.c101
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c48
-rw-r--r--drivers/i2c/busses/Kconfig524
-rw-r--r--drivers/i2c/busses/Makefile43
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c38
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c38
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c32
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c4
-rw-r--r--drivers/i2c/busses/i2c-amd756.c35
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c54
-rw-r--r--drivers/i2c/busses/i2c-cpm.c745
-rw-r--r--drivers/i2c/busses/i2c-davinci.c89
-rw-r--r--drivers/i2c/busses/i2c-elektor.c4
-rw-r--r--drivers/i2c/busses/i2c-gpio.c2
-rw-r--r--drivers/i2c/busses/i2c-hydra.c3
-rw-r--r--drivers/i2c/busses/i2c-i801.c284
-rw-r--r--drivers/i2c/busses/i2c-i810.c260
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c189
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-isch.c339
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-nforce2-s4985.c257
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c49
-rw-r--r--drivers/i2c/busses/i2c-ocores.c44
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c2
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c2
-rw-r--r--drivers/i2c/busses/i2c-piix4.c73
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c2
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c325
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c2
-rw-r--r--drivers/i2c/busses/i2c-savage4.c185
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c8
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c29
-rw-r--r--drivers/i2c/busses/i2c-sis630.c59
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c37
-rw-r--r--drivers/i2c/busses/i2c-stub.c6
-rw-r--r--drivers/i2c/busses/i2c-taos-evm.c5
-rw-r--r--drivers/i2c/busses/i2c-via.c5
-rw-r--r--drivers/i2c/busses/i2c-viapro.c31
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c2
-rw-r--r--drivers/i2c/chips/Kconfig17
-rw-r--r--drivers/i2c/chips/eeprom.c127
-rw-r--r--drivers/i2c/chips/isp1301_omap.c141
-rw-r--r--drivers/i2c/chips/max6875.c112
-rw-r--r--drivers/i2c/chips/pca9539.c100
-rw-r--r--drivers/i2c/chips/pcf8574.c106
-rw-r--r--drivers/i2c/chips/pcf8575.c84
-rw-r--r--drivers/i2c/chips/pcf8591.c102
-rw-r--r--drivers/i2c/i2c-core.c525
-rw-r--r--drivers/i2c/i2c-dev.c5
-rw-r--r--drivers/video/fb_ddc.c1
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c12
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c41
-rw-r--r--drivers/video/matrox/matroxfb_maven.c97
-rw-r--r--drivers/w1/masters/ds2482.c104
-rw-r--r--include/linux/i2c-algo-pcf.h8
-rw-r--r--include/linux/i2c-id.h3
-rw-r--r--include/linux/i2c.h44
89 files changed, 3841 insertions, 3164 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 5b3f31faed56..41013d4c35e2 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -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):
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
(superseded by xt_TOS/xt_tos target & match)
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
deleted file mode 100644
index 778210ee1583..000000000000
--- a/Documentation/i2c/busses/i2c-i810
+++ /dev/null
@@ -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.
diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage
deleted file mode 100644
index 703687902511..000000000000
--- a/Documentation/i2c/busses/i2c-prosavage
+++ /dev/null
@@ -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.
-
diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4
deleted file mode 100644
index 6ecceab618d3..000000000000
--- a/Documentation/i2c/busses/i2c-savage4
+++ /dev/null
@@ -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.
-
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
index a0cd8af2f408..10ca43cd1a72 100644
--- a/Documentation/i2c/chips/max6875
+++ b/Documentation/i2c/chips/max6875
@@ -49,7 +49,7 @@ $ modprobe max6875 force=0,0x50
The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
addresses. For example, for address 0x50, it also reserves 0x51.
-The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
+The even-address instance is called 'max6875', the odd one is 'dummy'.
Programming the chip using i2c-dev
diff --git a/Documentation/i2c/chips/pca9539 b/Documentation/i2c/chips/pca9539
index 1d81c530c4a5..6aff890088b1 100644
--- a/Documentation/i2c/chips/pca9539
+++ b/Documentation/i2c/chips/pca9539
@@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead.
Supported chips:
* Philips PCA9539
Prefix: 'pca9539'
- Addresses scanned: 0x74 - 0x77
+ Addresses scanned: none
Datasheet:
http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
@@ -23,6 +23,14 @@ The input sense can also be inverted.
The 16 lines are split between two bytes.
+Detection
+---------
+
+The PCA9539 is difficult to detect and not commonly found in PC machines,
+so you have to pass the I2C bus and address of the installed PCA9539
+devices explicitly to the driver at load time via the force=... parameter.
+
+
Sysfs entries
-------------
diff --git a/Documentation/i2c/chips/pcf8574 b/Documentation/i2c/chips/pcf8574
index 5c1ad1376b62..235815c075ff 100644
--- a/Documentation/i2c/chips/pcf8574
+++ b/Documentation/i2c/chips/pcf8574
@@ -4,13 +4,13 @@ Kernel driver pcf8574
Supported chips:
* Philips PCF8574
Prefix: 'pcf8574'
- Addresses scanned: I2C 0x20 - 0x27
+ Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html
* Philips PCF8574A
Prefix: 'pcf8574a'
- Addresses scanned: I2C 0x38 - 0x3f
+ Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html
@@ -38,12 +38,10 @@ For more informations see the datasheet.
Accessing PCF8574(A) via /sys interface
-------------------------------------
-! Be careful !
The PCF8574(A) is plainly impossible to detect ! Stupid chip.
-So every chip with address in the interval [20..27] and [38..3f] are
-detected as PCF8574(A). If you have other chips in this address
-range, the workaround is to load this module after the one
-for your others chips.
+So, you have to pass the I2C bus and address of the installed PCF857A
+and PCF8574A devices explicitly to the driver at load time via the
+force=... parameter.
On detection (i.e. insmod, modprobe et al.), directories are being
created for each detected PCF8574(A):
diff --git a/Documentation/i2c/chips/pcf8575 b/Documentation/i2c/chips/pcf8575
index 25f5698a61cf..40b268eb276f 100644
--- a/Documentation/i2c/chips/pcf8575
+++ b/Documentation/i2c/chips/pcf8575
@@ -40,12 +40,9 @@ Detection
---------
There is no method known to detect whether a chip on a given I2C address is
-a PCF8575 or whether it is any other I2C device. So there are two alternatives
-to let the driver find the installed PCF8575 devices:
-- Load this driver after any other I2C driver for I2C devices with addresses
- in the range 0x20 .. 0x27.
-- Pass the I2C bus and address of the installed PCF8575 devices explicitly to
- the driver at load time via the probe=... or force=... parameters.
+a PCF8575 or whether it is any other I2C device, so you have to pass the I2C
+bus and address of the installed PCF8575 devices explicitly to the driver at
+load time via the force=... parameter.
/sys interface
--------------
diff --git a/Documentation/i2c/fault-codes b/Documentation/i2c/fault-codes
new file mode 100644
index 000000000000..045765c0b9b5
--- /dev/null
+++ b/Documentation/i2c/fault-codes
@@ -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.
+
diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol
index 03f08fb491cc..24bfb65da17d 100644
--- a/Documentation/i2c/smbus-protocol
+++ b/Documentation/i2c/smbus-protocol
@@ -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.
-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.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index ee75cbace28d..6b61b3a2e90b 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -25,14 +25,29 @@ routines, and should be zero-initialized except for fields with data you
provide. A client structure holds device-specific information like the
driver model device node, and its I2C address.
+/* iff driver uses driver model ("new style") binding model: */
+
+static struct i2c_device_id foo_idtable[] = {
+ { "foo", my_id_for_foo },
+ { "bar", my_id_for_bar },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, foo_idtable);
+
static struct i2c_driver foo_driver = {
.driver = {
.name = "foo",
},
/* iff driver uses driver model ("new style") binding model: */
+ .id_table = foo_ids,
.probe = foo_probe,
.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: */
.attach_adapter = foo_attach_adapter,
@@ -173,10 +188,9 @@ handle may be used during foo_probe(). If foo_probe() reports success
(zero not a negative status code) it may save the handle and use it until
foo_remove() returns. That binding model is used by most Linux drivers.
-Drivers match devices when i2c_client.driver_name and the driver name are
-the same; this approach is used in several other busses that don't have
-device typing support in the hardware. The driver and module name should
-match, so hotplug/coldplug mechanisms will modprobe the driver.
+The probe function is called when an entry in the id_table name field
+matches the device's name. It is passed the entry that was matched so
+the driver knows which one in the table matched.
Device Creation (Standard driver model)
@@ -207,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client
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)
---------------------------------------
@@ -559,7 +598,6 @@ SMBus communication
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_write_byte(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@@ -568,30 +606,31 @@ SMBus communication
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
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,
u8 command, u8 length,
u8 *values);
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
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,
u8 command, u8 length,
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,
u8 command, u16 value);
extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
u8 command, u8 length,
u8 *values)
-All these transactions return -1 on failure. The 'write' transactions
-return 0 on success; the 'read' transactions return the read value, except
-for read_block, which returns the number of values read. The block buffers
-need not be longer than 32 bytes.
+All these transactions return a negative errno value on failure. The 'write'
+transactions return 0 on success; the 'read' transactions return the read
+value, except for block transactions, which return the number of values
+read. The block buffers need not be longer than 32 bytes.
You can read the file `smbus-protocol' for more information about the
actual SMBus protocol.
diff --git a/MAINTAINERS b/MAINTAINERS
index a658f552de52..1dd924c17a46 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1669,6 +1669,13 @@ L: linuxppc-embedded@ozlabs.org
L: linux-kernel@vger.kernel.org
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
P: Pantelis Antoniou
M: pantelis.antoniou@gmail.com
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 7fbaa8d648cd..ddc89c238280 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -476,6 +476,10 @@ static struct i2c_board_info __initdata h3_i2c_board_info[] = {
I2C_BOARD_INFO("tps65013", 0x48),
/* .irq = OMAP_GPIO_IRQ(??), */
},
+ {
+ I2C_BOARD_INFO("isp1301_omap", 0x2d),
+ .irq = OMAP_GPIO_IRQ(14),
+ },
};
static struct omap_gpio_switch h3_gpio_switches[] __initdata = {
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 0d28f6897c8e..2bf981d55ba8 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -18,6 +18,7 @@
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
+#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -392,6 +393,13 @@ static struct omap_board_config_kernel h4_config[] = {
{ OMAP_TAG_LCD, &h4_lcd_config },
};
+static struct i2c_board_info __initdata h4_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("isp1301_omap", 0x2d),
+ .irq = OMAP_GPIO_IRQ(125),
+ },
+};
+
static void __init omap_h4_init(void)
{
/*
@@ -412,6 +420,9 @@ static void __init omap_h4_init(void)
}
#endif
+ i2c_register_board_info(1, h4_i2c_board_info,
+ ARRAY_SIZE(h4_i2c_board_info));
+
platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
omap_board_config = h4_config;
omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile
index 1775755a2619..255d692bfa18 100644
--- a/arch/mips/sibyte/swarm/Makefile
+++ b/arch/mips/sibyte/swarm/Makefile
@@ -1,3 +1,4 @@
obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o
+obj-$(CONFIG_I2C_BOARDINFO) += swarm-i2c.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/sibyte/swarm/swarm-i2c.c b/arch/mips/sibyte/swarm/swarm-i2c.c
new file mode 100644
index 000000000000..4282ac9d01d2
--- /dev/null
+++ b/arch/mips/sibyte/swarm/swarm-i2c.c
@@ -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);
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 1d76de7d75c7..ba3a71e4a48c 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -2,7 +2,7 @@
* adm1025.c
*
* Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com>
- * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
*
* The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6
* voltages (including its own power source) and up to two temperatures
@@ -109,22 +109,34 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
* Functions declaration
*/
-static int adm1025_attach_adapter(struct i2c_adapter *adapter);
-static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind);
+static int adm1025_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int adm1025_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static void adm1025_init_client(struct i2c_client *client);
-static int adm1025_detach_client(struct i2c_client *client);
+static int adm1025_remove(struct i2c_client *client);
static struct adm1025_data *adm1025_update_device(struct device *dev);
/*
* Driver data (common to all clients)
*/
+static struct i2c_device_id adm1025_id[] = {
+ { "adm1025", adm1025 },
+ { "ne1619", ne1619 },
+ { }
+};
+
static struct i2c_driver adm1025_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "adm1025",
},
- .attach_adapter = adm1025_attach_adapter,
- .detach_client = adm1025_detach_client,
+ .probe = adm1025_probe,
+ .remove = adm1025_remove,
+ .id_table = adm1025_id,
+ .detect = adm1025_detect,
+ .address_data = &addr_data,
};
/*
@@ -132,7 +144,6 @@ static struct i2c_driver adm1025_driver = {
*/
struct adm1025_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
@@ -344,13 +355,6 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
* Real code
*/
-static int adm1025_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, adm1025_detect);
-}
-
static struct attribute *adm1025_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -403,31 +407,16 @@ static const struct attribute_group adm1025_group_in4 = {
.attrs = adm1025_attributes_in4,
};
-/*
- * The following function does more than just detection. If detection
- * succeeds, it also registers the new chip.
- */
-static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm1025_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct adm1025_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
const char *name = "";
u8 config;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &adm1025_driver;
+ return -ENODEV;
/*
* Now we do the remaining detection. A negative kind means that
@@ -448,8 +437,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
ADM1025_REG_STATUS2) & 0xBC) != 0x00) {
dev_dbg(&adapter->dev,
"ADM1025 detection failed at 0x%02x.\n",
- address);
- goto exit_free;
+ client->addr);
+ return -ENODEV;
}
}
@@ -465,7 +454,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
}
} else
if (man_id == 0xA1) { /* Philips */
- if (address != 0x2E
+ if (client->addr != 0x2E
&& (chip_id & 0xF0) == 0x20) { /* NE1619 */
kind = ne1619;
}
@@ -475,7 +464,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
@@ -484,23 +473,36 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == ne1619) {
name = "ne1619";
}
+ strlcpy(info->type, name, I2C_NAME_SIZE);
- /* We can fill in the remaining client fields */
- strlcpy(client->name, name, I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ return 0;
+}
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+static int adm1025_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adm1025_data *data;
+ int err;
+ u8 config;
+
+ data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
/* Initialize the ADM1025 chip */
adm1025_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group)))
- goto exit_detach;
+ goto exit_free;
/* Pin 11 is either in4 (+12V) or VID4 */
+ config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
if (!(config & 0x20)) {
if ((err = sysfs_create_group(&client->dev.kobj,
&adm1025_group_in4)))
@@ -518,8 +520,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove:
sysfs_remove_group(&client->dev.kobj, &adm1025_group);
sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
-exit_detach:
- i2c_detach_client(client);
exit_free:
kfree(data);
exit:
@@ -568,18 +568,14 @@ static void adm1025_init_client(struct i2c_client *client)
(reg&0x7E)|0x01);
}
-static int adm1025_detach_client(struct i2c_client *client)
+static int adm1025_remove(struct i2c_client *client)
{
struct adm1025_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adm1025_group);
sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index dc1f30e432ea..1692de369969 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -87,7 +87,6 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
struct f75375_data {
unsigned short addr;
- struct i2c_client *client;
struct device *hwmon_dev;
const char *name;
@@ -114,21 +113,12 @@ struct f75375_data {
s8 temp_max_hyst[2];
};
-static int f75375_attach_adapter(struct i2c_adapter *adapter);
-static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
-static int f75375_detach_client(struct i2c_client *client);
+static int f75375_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static int f75375_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int f75375_remove(struct i2c_client *client);
-static struct i2c_driver f75375_legacy_driver = {
- .driver = {
- .name = "f75375_legacy",
- },
- .attach_adapter = f75375_attach_adapter,
- .detach_client = f75375_detach_client,
-};
-
static const struct i2c_device_id f75375_id[] = {
{ "f75373", f75373 },
{ "f75375", f75375 },
@@ -137,12 +127,15 @@ static const struct i2c_device_id f75375_id[] = {
MODULE_DEVICE_TABLE(i2c, f75375_id);
static struct i2c_driver f75375_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "f75375",
},
.probe = f75375_probe,
.remove = f75375_remove,
.id_table = f75375_id,
+ .detect = f75375_detect,
+ .address_data = &addr_data,
};
static inline int f75375_read8(struct i2c_client *client, u8 reg)
@@ -607,22 +600,6 @@ static const struct attribute_group f75375_group = {
.attrs = f75375_attributes,
};
-static int f75375_detach_client(struct i2c_client *client)
-{
- int err;
-
- f75375_remove(client);
- err = i2c_detach_client(client);
- if (err) {
- dev_err(&client->dev,
- "Client deregistration failed, "
- "client not detached.\n");
- return err;
- }
- kfree(client);
- return 0;
-}
-
static void f75375_init(struct i2c_client *client, struct f75375_data *data,
struct f75375s_platform_data *f75375s_pdata)
{
@@ -651,7 +628,6 @@ static int f75375_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, data);
- data->client = client;
mutex_init(&data->update_lock);
data->kind = id->driver_data;
@@ -700,29 +676,13 @@ static int f75375_remove(struct i2c_client *client)
return 0;
}
-static int f75375_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, f75375_detect);
-}
-
-/* This function is called by i2c_probe */
-static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int f75375_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
u8 version = 0;
- int err = 0;
const char *name = "";
- struct i2c_device_id id;
-
- if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
- client->addr = address;
- client->adapter = adapter;
- client->driver = &f75375_legacy_driver;
if (kind < 0) {
u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
@@ -736,7 +696,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
dev_err(&adapter->dev,
"failed,%02X,%02X,%02X\n",
chipid, version, vendid);
- goto exit_free;
+ return -ENODEV;
}
}
@@ -746,43 +706,18 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
name = "f75373";
}
dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
- strlcpy(client->name, name, I2C_NAME_SIZE);
-
- if ((err = i2c_attach_client(client)))
- goto exit_free;
-
- strlcpy(id.name, name, I2C_NAME_SIZE);
- id.driver_data = kind;
- if ((err = f75375_probe(client, &id)) < 0)
- goto exit_detach;
+ strlcpy(info->type, name, I2C_NAME_SIZE);
return 0;
-
-exit_detach:
- i2c_detach_client(client);
-exit_free:
- kfree(client);
-exit:
- return err;
}
static int __init sensors_f75375_init(void)
{
- int status;
- status = i2c_add_driver(&f75375_driver);
- if (status)
- return status;
-
- status = i2c_add_driver(&f75375_legacy_driver);
- if (status)
- i2c_del_driver(&f75375_driver);
-
- return status;
+ return i2c_add_driver(&f75375_driver);
}
static void __exit sensors_f75375_exit(void)
{
- i2c_del_driver(&f75375_legacy_driver);
i2c_del_driver(&f75375_driver);
}
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 116287008083..100398b2c112 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -1,7 +1,7 @@
/*
* lm63.c - driver for the National Semiconductor LM63 temperature sensor
* with integrated fan control
- * Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org>
* Based on the lm90 driver.
*
* The LM63 is a sensor chip made by National Semiconductor. It measures
@@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63);
* Functions declaration
*/
-static int lm63_attach_adapter(struct i2c_adapter *adapter);
-static int lm63_detach_client(struct i2c_client *client);
+static int lm63_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm63_remove(struct i2c_client *client);
static struct lm63_data *lm63_update_device(struct device *dev);
-static int lm63_detect(struct i2c_adapter *adapter, int address, int kind);
+static int lm63_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static void lm63_init_client(struct i2c_client *client);
/*
* Driver data (common to all clients)
*/
+static struct i2c_device_id lm63_id[] = {
+ { "lm63", lm63 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm63_id);
+
static struct i2c_driver lm63_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm63",
},
- .attach_adapter = lm63_attach_adapter,
- .detach_client = lm63_detach_client,
+ .probe = lm63_probe,
+ .remove = lm63_remove,
+ .id_table = lm63_id,
+ .detect = lm63_detect,
+ .address_data = &addr_data,
};
/*
@@ -153,7 +165,6 @@ static struct i2c_driver lm63_driver = {
*/
struct lm63_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
@@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = {
* Real code
*/
-static int lm63_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm63_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm63_detect);
-}
-
-/*
- * The following function does more than just detection. If detection
- * succeeds, it also registers the new chip.
- */
-static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
-{
- struct i2c_client *new_client;
- struct lm63_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* The common I2C client data is placed right before the
- LM63-specific data. */
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &lm63_driver;
- new_client->flags = 0;
-
- /* Default to an LM63 if forced */
- if (kind == 0)
- kind = lm63;
+ return -ENODEV;
if (kind < 0) { /* must identify */
u8 man_id, chip_id, reg_config1, reg_config2;
@@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
dev_dbg(&adapter->dev, "Unsupported chip "
"(man_id=0x%02X, chip_id=0x%02X).\n",
man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
- strlcpy(new_client->name, "lm63", I2C_NAME_SIZE);
+ strlcpy(info->type, "lm63", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int lm63_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct lm63_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(new_client, data);
data->valid = 0;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/* Initialize the LM63 chip */
lm63_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm63_group)))
- goto exit_detach;
+ goto exit_free;
if (data->config & 0x04) { /* tachometer enabled */
if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm63_group_fan1)))
@@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
-exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client)
(data->config_fan & 0x20) ? "manual" : "auto");
}
-static int lm63_detach_client(struct i2c_client *client)
+static int lm63_remove(struct i2c_client *client)
{
struct lm63_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm63_group);
sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 36d5a8c3ad8c..071926a7d48e 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -52,7 +52,6 @@ I2C_CLIENT_INSMOD_1(lm77);
/* Each client has this additional data */
struct lm77_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid;
@@ -65,23 +64,34 @@ struct lm77_data {
u8 alarms;
};
-static int lm77_attach_adapter(struct i2c_adapter *adapter);
-static int lm77_detect(struct i2c_adapter *adapter, int address, int kind);
+static int lm77_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm77_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static void lm77_init_client(struct i2c_client *client);
-static int lm77_detach_client(struct i2c_client *client);
+static int lm77_remove(struct i2c_client *client);
static u16 lm77_read_value(struct i2c_client *client, u8 reg);
static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value);
static struct lm77_data *lm77_update_device(struct device *dev);
+static struct i2c_device_id lm77_id[] = {
+ { "lm77", lm77 },
+ { }
+};
+
/* This is the driver that will be inserted */
static struct i2c_driver lm77_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm77",
},
- .attach_adapter = lm77_attach_adapter,
- .detach_client = lm77_detach_client,
+ .probe = lm77_probe,
+ .remove = lm77_remove,
+ .id_table = lm77_id,
+ .detect = lm77_detect,
+ .address_data = &addr_data,
};
/* straight from the datasheet */
@@ -215,13 +225,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2);
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1);
-static int lm77_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm77_detect);
-}
-
static struct attribute *lm77_attributes[] = {
&dev_attr_temp1_input.attr,
&dev_attr_temp1_crit.attr,
@@ -240,32 +243,15 @@ static const struct attribute_group lm77_group = {
.attrs = lm77_attributes,
};
-/* This function is called by i2c_probe */
-static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm77_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct lm77_data *data;
- int err = 0;
- const char *name = "";
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
- goto exit;
-
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access lm77_{read,write}_value. */
- if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &lm77_driver;
- new_client->flags = 0;
+ return -ENODEV;
/* Here comes the remaining detection. Since the LM77 has no
register dedicated to identification, we have to rely on the
@@ -294,7 +280,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|| i2c_smbus_read_word_data(new_client, i + 3) != crit
|| i2c_smbus_read_word_data(new_client, i + 4) != min
|| i2c_smbus_read_word_data(new_client, i + 5) != max)
- goto exit_free;
+ return -ENODEV;
/* sign bits */
if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0)
@@ -302,51 +288,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|| ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0)
|| ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0)
|| ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0))
- goto exit_free;
+ return -ENODEV;
/* unused bits */
if (conf & 0xe0)
- goto exit_free;
+ return -ENODEV;
/* 0x06 and 0x07 return the last read value */
cur = i2c_smbus_read_word_data(new_client, 0);
if (i2c_smbus_read_word_data(new_client, 6) != cur
|| i2c_smbus_read_word_data(new_client, 7) != cur)
- goto exit_free;
+ return -ENODEV;
hyst = i2c_smbus_read_word_data(new_client, 2);
if (i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst)
- goto exit_free;
+ return -ENODEV;
min = i2c_smbus_read_word_data(new_client, 4);
if (i2c_smbus_read_word_data(new_client, 6) != min
|| i2c_smbus_read_word_data(new_client, 7) != min)
- goto exit_free;
+ return -ENODEV;
}
- /* Determine the chip type - only one kind supported! */
- if (kind <= 0)
- kind = lm77;
+ strlcpy(info->type, "lm77", I2C_NAME_SIZE);
- if (kind == lm77) {
- name = "lm77";
+ return 0;
+}
+
+static int lm77_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct lm77_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
}
- /* Fill in the remaining client fields and put it into the global list */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ i2c_set_clientdata(new_client, data);
data->valid = 0;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/* Initialize the LM77 chip */
lm77_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -358,20 +348,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &lm77_group);
-exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
return err;
}
-static int lm77_detach_client(struct i2c_client *client)
+static int lm77_remove(struct i2c_client *client)
{
struct lm77_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm77_group);
- i2c_detach_client(client);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 26c91c9d4769..373e5fce1e6d 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -108,7 +108,6 @@ static inline long TEMP_FROM_REG(u16 temp)
*/
struct lm80_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
@@ -132,10 +131,12 @@ struct lm80_data {
* Functions declaration
*/
-static int lm80_attach_adapter(struct i2c_adapter *adapter);
-static int lm80_detect(struct i2c_adapter *adapter, int address, int kind);
+static int lm80_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm80_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static void lm80_init_client(struct i2c_client *client);
-static int lm80_detach_client(struct i2c_client *client);
+static int lm80_remove(struct i2c_client *client);
static struct lm80_data *lm80_update_device(struct device *dev);
static int lm80_read_value(struct i2c_client *client, u8 reg);
static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
@@ -144,12 +145,21 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
* Driver data (common to all clients)
*/
+static struct i2c_device_id lm80_id[] = {
+ { "lm80", lm80 },
+ { }
+};
+
static struct i2c_driver lm80_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm80",
},
- .attach_adapter = lm80_attach_adapter,
- .detach_client = lm80_detach_client,
+ .probe = lm80_probe,
+ .remove = lm80_remove,
+ .id_table = lm80_id,
+ .detect = lm80_detect,
+ .address_data = &addr_data,
};
/*
@@ -383,13 +393,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
* Real code
*/
-static int lm80_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm80_detect);
-}
-
static struct attribute *lm80_attributes[] = {
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
@@ -442,53 +445,46 @@ static const struct attribute_group lm80_group = {
.attrs = lm80_attributes,
};
-static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm80_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ struct i2c_adapter *adapter = client->adapter;
int i, cur;
- struct i2c_client *client;
- struct lm80_data *data;
- int err = 0;
- const char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access lm80_{read,write}_value. */
- if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &lm80_driver;
+ return -ENODEV;
/* Now, we do the remaining detection. It is lousy. */
if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
- goto error_free;
+ return -ENODEV;
for (i = 0x2a; i <= 0x3d; i++) {
cur = i2c_smbus_read_byte_data(client, i);
if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
|| (i2c_smbus_read_byte_data(client, i + 0x80) != cur)
|| (i2c_smbus_read_byte_data(client, i + 0xc0) != cur))
- goto error_free;
+ return -ENODEV;
}
- /* Determine the chip type - only one kind supported! */
- kind = lm80;
- name = "lm80";
+ strlcpy(info->type, "lm80", I2C_NAME_SIZE);
- /* Fill in the remaining client fields */
- strlcpy(client->name, name, I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ return 0;
+}
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto error_free;
+static int lm80_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lm80_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
/* Initialize the LM80 chip */
lm80_init_client(client);
@@ -499,7 +495,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group)))
- goto error_detach;
+ goto error_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -511,23 +507,18 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
error_remove:
sysfs_remove_group(&client->dev.kobj, &lm80_group);
-error_detach:
- i2c_detach_client(client);
error_free:
kfree(data);
exit:
return err;
}
-static int lm80_detach_client(struct i2c_client *client)
+static int lm80_remove(struct i2c_client *client)
{
struct lm80_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm80_group);
- if ((err = i2c_detach_client(client)))
- return err;
kfree(data);
return 0;
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 6a8642fa25fb..8872ab25630c 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -1,7 +1,7 @@
/*
* lm83.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
- * Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
*
* Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
* a sensor chip made by National Semiconductor. It reports up to four
@@ -118,21 +118,34 @@ static const u8 LM83_REG_W_HIGH[] = {
* Functions declaration
*/
-static int lm83_attach_adapter(struct i2c_adapter *adapter);
-static int lm83_detect(struct i2c_adapter *adapter, int address, int kind);
-static int lm83_detach_client(struct i2c_client *client);
+static int lm83_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info);
+static int lm83_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm83_remove(struct i2c_client *client);
static struct lm83_data *lm83_update_device(struct device *dev);
/*
* Driver data (common to all clients)
*/
+static struct i2c_device_id lm83_id[] = {
+ { "lm83", lm83 },
+ { "lm82", lm82 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm83_id);
+
static struct i2c_driver lm83_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm83",
},
- .attach_adapter = lm83_attach_adapter,
- .detach_client = lm83_detach_client,
+ .probe = lm83_probe,
+ .remove = lm83_remove,
+ .id_table = lm83_id,
+ .detect = lm83_detect,
+ .address_data = &addr_data,
};
/*
@@ -140,7 +153,6 @@ static struct i2c_driver lm83_driver = {
*/
struct lm83_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
@@ -278,40 +290,15 @@ static const struct attribute_group lm83_group_opt = {
* Real code
*/
-static int lm83_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm83_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm83_detect);
-}
-
-/*
- * The following function does more than just detection. If detection
- * succeeds, it also registers the new chip.
- */
-static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
-{
- struct i2c_client *new_client;
- struct lm83_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* The common I2C client data is placed right after the
- * LM83-specific data. */
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &lm83_driver;
- new_client->flags = 0;
+ return -ENODEV;
/* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter
@@ -335,8 +322,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG)
& 0x41) != 0x00)) {
dev_dbg(&adapter->dev,
- "LM83 detection failed at 0x%02x.\n", address);
- goto exit_free;
+ "LM83 detection failed at 0x%02x.\n",
+ new_client->addr);
+ return -ENODEV;
}
}
@@ -361,7 +349,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
@@ -372,15 +360,27 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm82";
}
- /* We can fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ strlcpy(info->type, name, I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int lm83_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct lm83_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(new_client, data);
data->valid = 0;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/*
* Register sysfs hooks
* The LM82 can only monitor one external diode which is
@@ -389,9 +389,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
*/
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
- goto exit_detach;
+ goto exit_free;
- if (kind == lm83) {
+ if (id->driver_data == lm83) {
if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm83_group_opt)))
goto exit_remove_files;
@@ -408,26 +408,20 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm83_group);
sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt);
-exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
return err;
}
-static int lm83_detach_client(struct i2c_client *client)
+static int lm83_remove(struct i2c_client *client)
{
struct lm83_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm83_group);
sysfs_remove_group(&client->dev.kobj, &lm83_group_opt);
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index c31942e08246..0f981ac72a4d 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -1,6 +1,6 @@
/*
* lm92 - Hardware monitoring driver
- * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org>
*
* Based on the lm90 driver, with some ideas taken from the lm_sensors
* lm92 driver as well.
@@ -96,7 +96,6 @@ static struct i2c_driver lm92_driver;
/* Client data (each client gets its own) */
struct lm92_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
@@ -319,32 +318,15 @@ static const struct attribute_group lm92_group = {
.attrs = lm92_attributes,
};
-/* The following function does more than just detection. If detection
- succeeds, it also registers the new chip. */
-static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm92_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct lm92_data *data;
- int err = 0;
- char *name;
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA))
- goto exit;
-
- if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* Fill in enough client fields so that we can read from the chip,
- which is required for identication */
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &lm92_driver;
- new_client->flags = 0;
+ return -ENODEV;
/* A negative kind means that the driver was loaded with no force
parameter (default), so we must identify the chip. */
@@ -364,34 +346,36 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
kind = lm92; /* No separate prefix */
}
else
- goto exit_free;
- } else
- if (kind == 0) /* Default to an LM92 if forced */
- kind = lm92;
-
- /* Give it the proper name */
- if (kind == lm92) {
- name = "lm92";
- } else { /* Supposedly cannot happen */
- dev_dbg(&new_client->dev, "Kind out of range?\n");
- goto exit_free;
+ return -ENODEV;
}
- /* Fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ strlcpy(info->type, "lm92", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int lm92_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct lm92_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(new_client, data);
data->valid = 0;
mutex_init(&data->update_lock);
- /* Tell the i2c subsystem a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/* Initialize the chipset */
lm92_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -403,32 +387,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &lm92_group);
-exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
return err;
}
-static int lm92_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm92_detect);
-}
-
-static int lm92_detach_client(struct i2c_client *client)
+static int lm92_remove(struct i2c_client *client)
{
struct lm92_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm92_group);
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
}
@@ -438,12 +409,22 @@ static int lm92_detach_client(struct i2c_client *client)
* Module and driver stuff
*/
+static struct i2c_device_id lm92_id[] = {
+ { "lm92", lm92 },
+ /* max6635 could be added here */
+ { }
+};
+
static struct i2c_driver lm92_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm92",
},
- .attach_adapter = lm92_attach_adapter,
- .detach_client = lm92_detach_client,
+ .probe = lm92_probe,
+ .remove = lm92_remove,
+ .id_table = lm92_id,
+ .detect = lm92_detect,
+ .address_data = &addr_data,
};
static int __init sensors_lm92_init(void)
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 5e678f5c883d..e9baca808e0a 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -200,7 +200,6 @@ struct block1_t {
* Client-specific data
*/
struct lm93_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
@@ -2501,45 +2500,14 @@ static void lm93_init_client(struct i2c_client *client)
"chip to signal ready!\n");
}
-static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm93_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct lm93_data *data;
- struct i2c_client *client;
-
- int err = -ENODEV, func;
- void (*update)(struct lm93_data *, struct i2c_client *);
-
- /* choose update routine based on bus capabilities */
- func = i2c_get_functionality(adapter);
- if ( ((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
- (!disable_block) ) {
- dev_dbg(&adapter->dev,"using SMBus block data transactions\n");
- update = lm93_update_client_full;
- } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
- dev_dbg(&adapter->dev,"disabled SMBus block data "
- "transactions\n");
- update = lm93_update_client_min;
- } else {
- dev_dbg(&adapter->dev,"detect failed, "
- "smbus byte and/or word data not supported!\n");
- goto err_out;
- }
+ struct i2c_adapter *adapter = client->adapter;
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access lm78_{read,write}_value. */
-
- if ( !(data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL))) {
- dev_dbg(&adapter->dev,"out of memory!\n");
- err = -ENOMEM;
- goto err_out;
- }
-
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &lm93_driver;
+ if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN))
+ return -ENODEV;
/* detection */
if (kind < 0) {
@@ -2548,7 +2516,7 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
if (mfr != 0x01) {
dev_dbg(&adapter->dev,"detect failed, "
"bad manufacturer id 0x%02x!\n", mfr);
- goto err_free;
+ return -ENODEV;
}
}
@@ -2563,31 +2531,61 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == 0)
dev_dbg(&adapter->dev,
"(ignored 'force' parameter)\n");
- goto err_free;
+ return -ENODEV;
}
}
- /* fill in remaining client fields */
- strlcpy(client->name, "lm93", I2C_NAME_SIZE);
+ strlcpy(info->type, "lm93", I2C_NAME_SIZE);
dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n",
client->name, i2c_adapter_id(client->adapter),
client->addr);
+ return 0;
+}
+
+static int lm93_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lm93_data *data;
+ int err, func;
+ void (*update)(struct lm93_data *, struct i2c_client *);
+
+ /* choose update routine based on bus capabilities */
+ func = i2c_get_functionality(client->adapter);
+ if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
+ (!disable_block)) {
+ dev_dbg(&client->dev, "using SMBus block data transactions\n");
+ update = lm93_update_client_full;
+ } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
+ dev_dbg(&client->dev, "disabled SMBus block data "
+ "transactions\n");
+ update = lm93_update_client_min;
+ } else {
+ dev_dbg(&client->dev, "detect failed, "
+ "smbus byte and/or word data not supported!\n");
+ err = -ENODEV;
+ goto err_out;
+ }
+
+ data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL);
+ if (!data) {
+ dev_dbg(&client->dev, "out of memory!\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+ i2c_set_clientdata(client, data);
+
/* housekeeping */
data->valid = 0;
data->update = update;
mutex_init(&data->update_lock);
- /* tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto err_free;
-
/* initialize the chip */
lm93_init_client(client);
err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp);
if (err)
- goto err_detach;
+ goto err_free;
/* Register hwmon driver class */
data->hwmon_dev = hwmon_device_register(&client->dev);
@@ -2597,43 +2595,38 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
err = PTR_ERR(data->hwmon_dev);
dev_err(&client->dev, "error registering hwmon device.\n");
sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
-err_detach:
- i2c_detach_client(client);
err_free:
kfree(data);
err_out:
return err;
}
-/* This function is called when:
- * lm93_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and lm93_driver is still present) */
-static int lm93_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_probe(adapter, &addr_data, lm93_detect);
-}
-
-static int lm93_detach_client(struct i2c_client *client)
+static int lm93_remove(struct i2c_client *client)
{
struct lm93_data *data = i2c_get_clientdata(client);
- int err = 0;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
- err = i2c_detach_client(client);
- if (!err)
- kfree(data);
- return err;
+ kfree(data);
+ return 0;
}
+static struct i2c_device_id lm93_id[] = {
+ { "lm93", lm93 },
+ { }
+};
+
static struct i2c_driver lm93_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm93",
},
- .attach_adapter = lm93_attach_adapter,
- .detach_client = lm93_detach_client,
+ .probe = lm93_probe,
+ .remove = lm93_remove,
+ .id_table = lm93_id,
+ .detect = lm93_detect,
+ .address_data = &addr_data,
};
static int __init lm93_init(void)
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 7e7267a04544..8130944f254c 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -79,23 +79,33 @@ I2C_CLIENT_INSMOD_1(max1619);
* Functions declaration
*/
-static int max1619_attach_adapter(struct i2c_adapter *adapter);
-static int max1619_detect(struct i2c_adapter *adapter, int address,
- int kind);
+static int max1619_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int max1619_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static void max1619_init_client(struct i2c_client *client);
-static int max1619_detach_client(struct i2c_client *client);
+static int max1619_remove(struct i2c_client *client);
static struct max1619_data *max1619_update_device(struct device *dev);
/*
* Driver data (common to all clients)
*/
+static struct i2c_device_id max1619_id[] = {
+ { "max1619", max1619 },
+ { }
+};
+
static struct i2c_driver max1619_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "max1619",
},
- .attach_adapter = max1619_attach_adapter,
- .detach_client = max1619_detach_client,
+ .probe = max1619_probe,
+ .remove = max1619_remove,
+ .id_table = max1619_id,
+ .detect = max1619_detect,
+ .address_data = &addr_data,
};
/*
@@ -103,7 +113,6 @@ static struct i2c_driver max1619_driver = {
*/
struct max1619_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
@@ -208,41 +217,15 @@ static const struct attribute_group max1619_group = {
* Real code
*/
-static int max1619_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, max1619_detect);
-}
-
-/*
- * The following function does more than just detection. If detection
- * succeeds, it also registers the new chip.
- */
-static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max1619_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct max1619_data *data;
- int err = 0;
- const char *name = "";
+ struct i2c_adapter *adapter = new_client->adapter;
u8 reg_config=0, reg_convrate=0, reg_status=0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* The common I2C client data is placed right before the
- MAX1619-specific data. */
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &max1619_driver;
- new_client->flags = 0;
+ return -ENODEV;
/*
* Now we do the remaining detection. A negative kind means that
@@ -265,8 +248,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
|| reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) {
dev_dbg(&adapter->dev,
"MAX1619 detection failed at 0x%02x.\n",
- address);
- goto exit_free;
+ new_client->addr);
+ return -ENODEV;
}
}
@@ -285,28 +268,37 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
- if (kind == max1619)
- name = "max1619";
+ strlcpy(info->type, "max1619", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int max1619_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct max1619_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
- /* We can fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ i2c_set_clientdata(new_client, data);
data->valid = 0;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/* Initialize the MAX1619 chip */
max1619_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -318,8 +310,6 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &max1619_group);
-exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -341,17 +331,13 @@ static void max1619_init_client(struct i2c_client *client)
config & 0xBF); /* run */
}
-static int max1619_detach_client(struct i2c_client *client)
+static int max1619_remove(struct i2c_client *client)
{
struct max1619_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &max1619_group);
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 52d528b76cc3..896f4df74490 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -104,22 +104,33 @@ I2C_CLIENT_INSMOD_1(max6650);
#define DIV_FROM_REG(reg) (1 << (reg & 7))
-static int max6650_attach_adapter(struct i2c_adapter *adapter);
-static int max6650_detect(struct i2c_adapter *adapter, int address, int kind);
+static int max6650_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int max6650_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
static int max6650_init_client(struct i2c_client *client);
-static int max6650_detach_client(struct i2c_client *client);
+static int max6650_remove(struct i2c_client *client);
static struct max6650_data *max6650_update_device(struct device *dev);
/*
* Driver data (common to all clients)
*/
+static struct i2c_device_id max6650_id[] = {
+ { "max6650", max6650 },
+ { }
+};
+
static struct i2c_driver max6650_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "max6650",
},
- .attach_adapter = max6650_attach_adapter,
- .detach_client = max6650_detach_client,
+ .probe = max6650_probe,
+ .remove = max6650_remove,
+ .id_table = max6650_id,
+ .detect = max6650_detect,
+ .address_data = &addr_data,
};
/*
@@ -128,7 +139,6 @@ static struct i2c_driver max6650_driver = {
struct max6650_data
{
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
@@ -437,47 +447,21 @@ static struct attribute_group max6650_attr_grp = {
* Real code
*/
-static int max6650_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max6650_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- if (!(adapter->class & I2C_CLASS_HWMON)) {
- dev_dbg(&adapter->dev,
- "FATAL: max6650_attach_adapter class HWMON not set\n");
- return 0;
- }
-
- return i2c_probe(adapter, &addr_data, max6650_detect);
-}
-
-/*
- * The following function does more than just detection. If detection
- * succeeds, it also registers the new chip.
- */
-
-static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
-{
- struct i2c_client *client;
- struct max6650_data *data;
- int err = -ENODEV;
+ struct i2c_adapter *adapter = client->adapter;
+ int address = client->addr;
dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support "
"byte read mode, skipping.\n");
- return 0;
- }
-
- if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
- dev_err(&adapter->dev, "max6650: out of memory.\n");
- return -ENOMEM;
+ return -ENODEV;
}
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &max6650_driver;
-
/*
* Now we do the remaining detection. A negative kind means that
* the driver was loaded with no force parameter (default), so we
@@ -501,28 +485,40 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) {
dev_dbg(&adapter->dev,
"max6650: detection failed at 0x%02x.\n", address);
- goto err_free;
+ return -ENODEV;
}
dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address);
- strlcpy(client->name, "max6650", I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ strlcpy(info->type, "max6650", I2C_NAME_SIZE);
- if ((err = i2c_attach_client(client))) {
- dev_err(&adapter->dev, "max6650: failed to attach client.\n");
- goto err_free;
+ return 0;
+}
+
+static int max6650_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max6650_data *data;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
+ dev_err(&client->dev, "out of memory.\n");
+ return -ENOMEM;
}
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
/*
* Initialize the max6650 chip
*/
- if (max6650_init_client(client))
- goto err_detach;
+ err = max6650_init_client(client);
+ if (err)
+ goto err_free;
err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp);
if (err)
- goto err_detach;
+ goto err_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (!IS_ERR(data->hwmon_dev))
@@ -531,24 +527,19 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
err = PTR_ERR(data->hwmon_dev);
dev_err(&client->dev, "error registering hwmon device.\n");
sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
-err_detach:
- i2c_detach_client(client);
err_free:
kfree(data);
return err;
}
-static int max6650_detach_client(struct i2c_client *client)
+static int max6650_remove(struct i2c_client *client)
{
struct max6650_data *data = i2c_get_clientdata(client);
- int err;
sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
hwmon_device_unregister(data->hwmon_dev);
- err = i2c_detach_client(client);
- if (!err)
- kfree(data);
- return err;
+ kfree(data);
+ return 0;
}
static int max6650_init_client(struct i2c_client *client)
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index 3c9db6598ba7..9402b29b7900 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -96,7 +96,6 @@ static inline int TEMP_FROM_REG(s8 val)
}
struct smsc47m192_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
@@ -114,18 +113,28 @@ struct smsc47m192_data {
u8 vrm;
};
-static int smsc47m192_attach_adapter(struct i2c_adapter *adapter);
-static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
- int kind);
-static int smsc47m192_detach_client(struct i2c_client *client);
+static int smsc47m192_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int smsc47m192_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int smsc47m192_remove(struct i2c_client *client);
static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
+static struct i2c_device_id smsc47m192_id[] = {
+ { "smsc47m192", smsc47m192 },
+ { }
+};
+
static struct i2c_driver smsc47m192_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "smsc47m192",
},
- .attach_adapter = smsc47m192_attach_adapter,
- .detach_client = smsc47m192_detach_client,
+ .probe = smsc47m192_probe,
+ .remove = smsc47m192_remove,
+ .id_table = smsc47m192_id,
+ .detect = smsc47m192_detect,
+ .address_data = &addr_data,
};
/* Voltages */
@@ -440,17 +449,6 @@ static const struct attribute_group smsc47m192_group_in4 = {
.attrs = smsc47m192_attributes_in4,
};
-/* This function is called when:
- * smsc47m192_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and smsc47m192_driver is still present) */
-static int smsc47m192_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, smsc47m192_detect);
-}
-
static void smsc47m192_init_client(struct i2c_client *client)
{
int i;
@@ -481,31 +479,15 @@ static void smsc47m192_init_client(struct i2c_client *client)
}
}
-/* This function is called by i2c_probe */
-static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
- int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int smsc47m192_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct smsc47m192_data *data;
- int err = 0;
- int version, config;
+ struct i2c_adapter *adapter = client->adapter;
+ int version;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &smsc47m192_driver;
-
- if (kind == 0)
- kind = smsc47m192;
+ return -ENODEV;
/* Detection criteria from sensors_detect script */
if (kind < 0) {
@@ -523,26 +505,39 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
} else {
dev_dbg(&adapter->dev,
"SMSC47M192 detection failed at 0x%02x\n",
- address);
- goto exit_free;
+ client->addr);
+ return -ENODEV;
}
}
- /* Fill in the remaining client fields and put into the global list */
- strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE);
+ strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int smsc47m192_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct smsc47m192_data *data;
+ int config;
+ int err;
+
+ data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
data->vrm = vid_which_vrm();
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
-
/* Initialize the SMSC47M192 chip */
smsc47m192_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group)))
- goto exit_detach;
+ goto exit_free;
/* Pin 110 is either in4 (+12V) or VID4 */
config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
@@ -563,26 +558,20 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
-exit_detach:
- i2c_detach_client(client);
exit_free:
kfree(data);
exit:
return err;
}
-static int smsc47m192_detach_client(struct i2c_client *client)
+static int smsc47m192_remove(struct i2c_client *client)
{
struct smsc47m192_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 35812823787b..eb8f72ca02f4 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries)
{
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
- int i, ret = -1;
+ int i, ret = 0;
for (i = 0; i <= retries; i++) {
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;
ret = try_address(i2c_adap, addr, retries);
if ((ret != 1) && !nak_ok)
- return -EREMOTEIO;
+ return -ENXIO;
}
return 0;
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index e954a20b97a6..d50b329a3c94 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
}
if (state != 0xf8) {
dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
- return -EIO;
+ return -EAGAIN;
}
DEB1("{{{ XFER %d messages\n", num);
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 8907b0191677..1e328d19cd6d 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
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) {
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);
}
if (*status & I2C_PCF_LAB) {
- 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);
- /* 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)));
+ handle_lab(adap, status);
return(-EINTR);
}
#endif
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 48438cc5d0ca..4aeefa6d5ac7 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -4,6 +4,8 @@
menu "I2C Hardware Bus support"
+comment "PC SMBus host controller drivers"
+
config I2C_ALI1535
tristate "ALI 1535"
depends on PCI
@@ -73,6 +75,238 @@ config I2C_AMD8111
This driver can also be built as a module. If so, the module
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_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 "Graphics adapter I2C/DDC channel drivers"
+
+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.
+
+comment "External I2C/SMBus adapter drivers"
+
+config I2C_PARPORT
+ tristate "Parallel port adapter"
+ depends on PARPORT
+ select I2C_ALGOBIT
+ help
+ This supports parallel port I2C adapters such as the ones made by
+ Philips or Velleman, Analog Devices evaluation boards, and more.
+ Basically any adapter using the parallel port as an I2C bus with
+ no extra chipset is supported by this driver, or could be.
+
+ This driver is a replacement for (and was inspired by) an older
+ driver named i2c-philips-par. The new driver supports more devices,
+ and makes it easier to add support for new devices.
+
+ An adapter type parameter is now mandatory. Please read the file
+ Documentation/i2c/busses/i2c-parport for details.
+
+ Another driver exists, named i2c-parport-light, which doesn't depend
+ on the parport driver. This is meant for embedded systems. Don't say
+ Y here if you intend to say Y or M there.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-parport.
+
+config I2C_PARPORT_LIGHT
+ tristate "Parallel port adapter (light)"
+ select I2C_ALGOBIT
+ help
+ This supports parallel port I2C adapters such as the ones made by
+ Philips or Velleman, Analog Devices evaluation boards, and more.
+ Basically any adapter using the parallel port as an I2C bus with
+ no extra chipset is supported by this driver, or could be.
+
+ This driver is a light version of i2c-parport. It doesn't depend
+ on the parport driver, and uses direct I/O access instead. This
+ might be preferred on embedded systems where wasting memory for
+ the clean but heavy parport handling is not an option. The
+ drawback is a reduced portability and the impossibility to
+ daisy-chain other parallel port devices.
+
+ Don't say Y here if you said Y or M to i2c-parport. Saying M to
+ both is possible but both modules should not be loaded at the same
+ time.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-parport-light.
+
+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_TINY_USB
+ tristate "Tiny-USB adapter"
+ 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.
+
+comment "Other I2C/SMBus bus drivers"
+
config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
@@ -101,10 +335,9 @@ config I2C_AU1550
config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support"
depends on BLACKFIN
+ depends on !BF561 && !BF531 && !BF532 && !BF533
help
- This is the TWI I2C device driver for Blackfin BF522, BF525,
- BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
- please don't use this driver.
+ This is the I2C bus driver for Blackfin on-chip TWI interface.
This driver can also be built as a module. If so, the module
will be called i2c-bfin-twi.
@@ -117,6 +350,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
help
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
tristate "DaVinci I2C driver"
depends on ARCH_DAVINCI
@@ -161,51 +404,6 @@ config I2C_HYDRA
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
@@ -222,31 +420,6 @@ config I2C_PXA_SLAVE
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
tristate "IBM PPC 4xx on-chip I2C interface"
depends on 4xx
@@ -267,6 +440,16 @@ config I2C_IOP3XX
This driver can also be built as a module. If so, the module
will be called i2c-iop3xx.
+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_IXP2000
tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
depends on ARCH_IXP2000
@@ -305,16 +488,6 @@ config I2C_MPC
This driver can also be built as a module. If so, the module
will be called i2c-mpc.
-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_OCORES
tristate "OpenCores I2C Controller"
depends on EXPERIMENTAL
@@ -336,77 +509,12 @@ config I2C_OMAP
Like OMAP1510/1610/1710/5912 and OMAP242x.
For details see http://www.ti.com/omap.
-config I2C_PARPORT
- tristate "Parallel port adapter"
- depends on PARPORT
- select I2C_ALGOBIT
- help
- This supports parallel port I2C adapters such as the ones made by
- Philips or Velleman, Analog Devices evaluation boards, and more.
- Basically any adapter using the parallel port as an I2C bus with
- no extra chipset is supported by this driver, or could be.
-
- This driver is a replacement for (and was inspired by) an older
- driver named i2c-philips-par. The new driver supports more devices,
- and makes it easier to add support for new devices.
-
- An adapter type parameter is now mandatory. Please read the file
- Documentation/i2c/busses/i2c-parport for details.
-
- Another driver exists, named i2c-parport-light, which doesn't depend
- on the parport driver. This is meant for embedded systems. Don't say
- Y here if you intend to say Y or M there.
-
- This support is also available as a module. If so, the module
- will be called i2c-parport.
-
-config I2C_PARPORT_LIGHT
- tristate "Parallel port adapter (light)"
- select I2C_ALGOBIT
- help
- This supports parallel port I2C adapters such as the ones made by
- Philips or Velleman, Analog Devices evaluation boards, and more.
- Basically any adapter using the parallel port as an I2C bus with
- no extra chipset is supported by this driver, or could be.
-
- This driver is a light version of i2c-parport. It doesn't depend
- on the parport driver, and uses direct I/O access instead. This
- might be preferred on embedded systems where wasting memory for
- the clean but heavy parport handling is not an option. The
- drawback is a reduced portability and the impossibility to
- daisy-chain other parallel port devices.
-
- Don't say Y here if you said Y or M to i2c-parport. Saying M to
- both is possible but both modules should not be loaded at the same
- time.
-
- This support is also available as a module. If so, the module
- will be called i2c-parport-light.
-
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_PROSAVAGE
- tristate "S3/VIA (Pro)Savage (DEPRECATED)"
- default n
- depends on PCI
- select I2C_ALGOBIT
- help
- If you say yes to this option, support will be included for the
- I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8
- graphics processors.
- chipsets supported:
- S3/VIA KM266/VT8375 aka ProSavage8
- S3/VIA KM133/VT8365 aka Savage4
-
- This driver is deprecated in favor of the savagefb driver.
-
- This support is also available as a module. If so, the module
- will be called i2c-prosavage.
-
config I2C_S3C2410
tristate "S3C2410 I2C Driver"
depends on ARCH_S3C2410
@@ -414,20 +522,6 @@ config I2C_S3C2410
Say Y here to include support for I2C controller in the
Samsung S3C2410 based System-on-Chip devices.
-config I2C_SAVAGE4
- tristate "S3 Savage 4 (DEPRECATED)"
- default n
- depends on PCI
- select I2C_ALGOBIT
- help
- If you say yes to this option, support will be included for the
- S3 Savage 4 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
- will be called i2c-savage4.
-
config I2C_SIBYTE
tristate "SiByte SMBus interface"
depends on SIBYTE_SB1xxx_SOC
@@ -489,60 +583,6 @@ config SCx200_ACB
This support is also available as a module. If so, the module
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
@@ -556,17 +596,6 @@ config 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
@@ -588,47 +617,6 @@ config I2C_ACORN
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
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e8c882a5ea66..bc6fc364459d 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -2,57 +2,64 @@
# Makefile for the i2c bus drivers.
#
+# PC SMBus host controller drivers
obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o
obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o
obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
+obj-$(CONFIG_I2C_I801) += i2c-i801.o
+obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
+obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o
+obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
+obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
+obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
+obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
+obj-$(CONFIG_I2C_VIA) += i2c-via.o
+obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
+
+# Graphics adapter I2C/DDC channel drivers
+obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.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
+
+# Other I2C/SMBus bus drivers
+obj-$(CONFIG_I2C_ACORN) += i2c-acorn.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_CPM) += i2c-cpm.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_I810) += i2c-i810.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
+obj-$(CONFIG_I2C_ISCH) += i2c-isch.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_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
-obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
-obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_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_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
-obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
+obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.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_SIS630) += i2c-sis630.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_VIAPRO) += i2c-viapro.o
-obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index f14372ac2fc5..9cead9b9458e 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -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>,
Philip Edelbrock <phil@netroedge.com>,
Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -61,6 +59,7 @@
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#include <asm/io.h>
@@ -159,6 +158,11 @@ static int ali1535_setup(struct pci_dev *dev)
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,
ali1535_driver.name)) {
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,
"SMBus reset failed! (0x%02x) - controller or "
"device on bus is probably hung\n", temp);
- return -1;
+ return -EBUSY;
}
} else {
/* 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 (timeout >= MAX_TIMEOUT) {
- result = -1;
+ result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n");
}
if (temp & ALI1535_STS_FAIL) {
- result = -1;
+ result = -EIO;
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.
*/
if (temp & ALI1535_STS_BUSERR) {
- result = -1;
+ result = -ENXIO;
dev_dbg(&adap->dev,
"Error: no response or bus collision ADD=%02x\n",
inb_p(SMBHSTADD));
@@ -303,13 +307,13 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* haven't ever seen this */
if (temp & ALI1535_STS_DEV) {
- result = -1;
+ result = -EIO;
dev_err(&adap->dev, "Error: device error\n");
}
/* check to see if the "command complete" indication is set */
if (!(temp & ALI1535_STS_DONE)) {
- result = -1;
+ result = -ETIMEDOUT;
dev_err(&adap->dev, "Error: command never completed\n");
}
@@ -332,7 +336,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
return result;
}
-/* Return -1 on error. */
+/* Return negative errno on error. */
static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command,
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);
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:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD);
@@ -418,13 +418,15 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
outb_p(data->block[i], SMBBLKDAT);
}
break;
+ default:
+ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+ result = -EOPNOTSUPP;
+ goto EXIT;
}
- if (ali1535_transaction(adap)) {
- /* Error in transaction */
- result = -1;
+ result = ali1535_transaction(adap);
+ if (result)
goto EXIT;
- }
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) {
result = 0;
@@ -475,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI1535,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 6b68074e518a..fc3e5b026423 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -21,6 +21,7 @@
#include <linux/i2c.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#define ALI1563_MAX_TIMEOUT 500
#define ALI1563_SMBBA 0x80
@@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
{
u32 data;
int timeout;
+ int status = -EIO;
dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
"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 */
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
data = inb_p(SMB_HST_STS);
+ status = -ETIMEDOUT;
}
/* device error - no response, ignore the autodetection case */
- if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
- dev_err(&a->dev, "Device error!\n");
+ if (data & HST_STS_DEVERR) {
+ if (size != HST_CNTL2_QUICK)
+ dev_err(&a->dev, "Device error!\n");
+ status = -ENXIO;
}
-
/* bus collision */
if (data & HST_STS_BUSERR) {
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);
}
- return -1;
+ return status;
}
static int ali1563_block_start(struct i2c_adapter * a)
{
u32 data;
int timeout;
+ int status = -EIO;
dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
"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))
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",
- timeout ? "Timeout " : "",
+ timeout ? "" : "Timeout ",
data & HST_STS_FAIL ? "Transaction Failed " : "",
data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
data & HST_STS_DEVERR ? "Device Error " : "",
!(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)
@@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
/* Map the size to what the chip understands */
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:
size = HST_CNTL2_QUICK;
break;
@@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
case I2C_SMBUS_BLOCK_DATA:
size = HST_CNTL2_BLOCK;
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);
@@ -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,
ali1563_pci_driver.name)) {
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 = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI1563,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ali1563_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 93bf87d70961..234fdde7d40e 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -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
Philip Edelbrock <phil@netroedge.com> and
Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -68,6 +66,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#include <asm/io.h>
/* ALI15X3 SMBus address offsets */
@@ -166,6 +165,10 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
if(force_addr)
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,
ali15x3_driver.name)) {
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) - "
"controller or device on bus is probably hung\n",
temp);
- return -1;
+ return -EBUSY;
}
} else {
/* 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 (timeout >= MAX_TIMEOUT) {
- result = -1;
+ result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n");
}
if (temp & ALI15X3_STS_TERM) {
- result = -1;
+ result = -EIO;
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.
*/
if (temp & ALI15X3_STS_COLL) {
- result = -1;
+ result = -ENXIO;
dev_dbg(&adap->dev,
"Error: no response or bus collision ADD=%02x\n",
inb_p(SMBHSTADD));
@@ -328,7 +331,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
/* haven't ever seen this */
if (temp & ALI15X3_STS_DEV) {
- result = -1;
+ result = -EIO;
dev_err(&adap->dev, "Error: device error\n");
}
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 -1 on error. */
+/* Return negative errno on error. */
static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data)
@@ -362,9 +365,6 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
}
switch (size) {
- case I2C_SMBUS_PROC_CALL:
- dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
- return -1;
case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD);
@@ -417,12 +417,16 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
}
size = ALI15X3_BLOCK_DATA;
break;
+ default:
+ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
}
outb_p(size, SMBHSTCNT); /* output command */
- if (ali15x3_transaction(adap)) /* Error in transaction */
- return -1;
+ temp = ali15x3_transaction(adap);
+ if (temp)
+ return temp;
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
return 0;
@@ -470,7 +474,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI15X3,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index c38a0a112208..2f150e33c74c 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -58,7 +58,7 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
/* We exclude the multiplexed addresses */
if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
|| addr == 0x18)
- return -1;
+ return -ENXIO;
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 */
if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
- return -1;
+ return -ENXIO;
mutex_lock(&amd756_lock);
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 43508d61eb7c..1ea39254dac6 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -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>
Shamelessly ripped from i2c-piix4.c:
@@ -45,6 +42,7 @@
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#include <asm/io.h>
/* AMD756 SMBus address offsets */
@@ -151,17 +149,17 @@ static int amd756_transaction(struct i2c_adapter *adap)
}
if (temp & GS_PRERR_STS) {
- result = -1;
+ result = -ENXIO;
dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
}
if (temp & GS_COL_STS) {
- result = -1;
+ result = -EIO;
dev_warn(&adap->dev, "SMBus collision!\n");
}
if (temp & GS_TO_STS) {
- result = -1;
+ result = -ETIMEDOUT;
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);
msleep(100);
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,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data)
{
int i, len;
+ int status;
- /** TODO: Should I supporte the 10-bit transfers? */
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:
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMB_HOST_ADDRESS);
@@ -251,13 +245,17 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
}
size = AMD756_BLOCK_DATA;
break;
+ default:
+ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
}
/* How about enabling interrupts... */
outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
- if (amd756_transaction(adap)) /* Error in transaction */
- return -1;
+ status = amd756_transaction(adap);
+ if (status)
+ return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
return 0;
@@ -301,7 +299,7 @@ static const struct i2c_algorithm smbus_algorithm = {
struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_AMD756,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -368,6 +366,11 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
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)) {
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
amd756_ioport);
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 5d1a27ef2504..3972208876b3 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/acpi.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
@@ -77,7 +78,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
if (!timeout) {
dev_warn(&smbus->dev->dev,
"Timeout while waiting for IBF to clear\n");
- return -1;
+ return -ETIMEDOUT;
}
return 0;
@@ -93,7 +94,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
if (!timeout) {
dev_warn(&smbus->dev->dev,
"Timeout while waiting for OBF to set\n");
- return -1;
+ return -ETIMEDOUT;
}
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,
unsigned char *data)
{
- if (amd_ec_wait_write(smbus))
- return -1;
+ int status;
+
+ status = amd_ec_wait_write(smbus);
+ if (status)
+ return status;
outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
- if (amd_ec_wait_write(smbus))
- return -1;
+ status = amd_ec_wait_write(smbus);
+ if (status)
+ return status;
outb(address, smbus->base + AMD_EC_DATA);
- if (amd_ec_wait_read(smbus))
- return -1;
+ status = amd_ec_wait_read(smbus);
+ if (status)
+ return status;
*data = inb(smbus->base + AMD_EC_DATA);
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,
unsigned char data)
{
- if (amd_ec_wait_write(smbus))
- return -1;
+ int status;
+
+ status = amd_ec_wait_write(smbus);
+ if (status)
+ return status;
outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
- if (amd_ec_wait_write(smbus))
- return -1;
+ status = amd_ec_wait_write(smbus);
+ if (status)
+ return status;
outb(address, smbus->base + AMD_EC_DATA);
- if (amd_ec_wait_write(smbus))
- return -1;
+ status = amd_ec_wait_write(smbus);
+ if (status)
+ return status;
outb(data, smbus->base + AMD_EC_DATA);
return 0;
@@ -267,12 +278,17 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
default:
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_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);
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))
- return -1;
+ return -EIO;
if (read_write == I2C_SMBUS_WRITE)
return 0;
@@ -359,6 +375,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
smbus->base = pci_resource_start(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)) {
error = -EBUSY;
goto out_kfree;
@@ -368,7 +388,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus2 AMD8111 adapter at %04x", smbus->base);
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_data = smbus;
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
new file mode 100644
index 000000000000..652acd7b5943
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -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_iic_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_BUSY | 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 %p, i2c_addr 0x%04x\n",
+ cpm->i2c_ram, cpm->i2c_addr);
+ 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");
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 7ecbfc429b19..af3846eda985 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -85,6 +85,7 @@
#define DAVINCI_I2C_MDR_MST (1 << 10)
#define DAVINCI_I2C_MDR_TRX (1 << 9)
#define DAVINCI_I2C_MDR_XA (1 << 8)
+#define DAVINCI_I2C_MDR_RM (1 << 7)
#define DAVINCI_I2C_MDR_IRS (1 << 5)
#define DAVINCI_I2C_IMR_AAS (1 << 6)
@@ -112,6 +113,7 @@ struct davinci_i2c_dev {
u8 *buf;
size_t buf_len;
int irq;
+ u8 terminate;
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;
u16 psc;
u32 clk;
+ u32 d;
u32 clkh;
u32 clkl;
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
*/
- 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;
- clkh = (50 * clk) / 100;
+ clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1);
+ clkh = clk >> 1;
clkl = clk - clkh;
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_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",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
dev_dbg(dev->dev, "CLKL = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
dev_dbg(dev->dev, "CLKH = %d\n",
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: */
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_platform_data *pdata = dev->dev->platform_data;
u32 flag;
- u32 stat;
u16 w;
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);
- init_completion(&dev->cmd_complete);
+ INIT_COMPLETION(dev->cmd_complete);
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
* start bit */
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);
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
+ dev->terminate = 0;
/* write the data into mode register */
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
DAVINCI_I2C_TIMEOUT);
- dev->buf_len = 0;
- if (r < 0)
- return r;
-
if (r == 0) {
dev_err(dev->dev, "controller timed out\n");
i2c_davinci_init(dev);
+ dev->buf_len = 0;
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 */
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++) {
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)
return ret;
}
-
- dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
-
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);
}
+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
* occurs.
@@ -372,12 +411,15 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
switch (stat) {
case DAVINCI_I2C_IVR_AL:
+ /* Arbitration lost, must retry */
dev->cmd_err |= DAVINCI_I2C_STR_AL;
+ dev->buf_len = 0;
complete(&dev->cmd_complete);
break;
case DAVINCI_I2C_IVR_NACK:
dev->cmd_err |= DAVINCI_I2C_STR_NACK;
+ dev->buf_len = 0;
complete(&dev->cmd_complete);
break;
@@ -399,9 +441,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG,
DAVINCI_I2C_IMR_RRDY);
- } else
- dev_err(dev->dev, "RDR IRQ while no "
- "data requested\n");
+ } else {
+ /* signal can terminate transfer */
+ terminate_read(dev);
+ }
break;
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_IMR_REG,
w);
- } else
- dev_err(dev->dev, "TDR IRQ while no data to "
- "send\n");
+ } else {
+ /* signal can terminate transfer */
+ terminate_write(dev);
+ }
break;
case DAVINCI_I2C_IVR_SCD:
@@ -475,6 +519,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
goto err_release_region;
}
+ init_completion(&dev->cmd_complete);
dev->dev = get_device(&pdev->dev);
dev->irq = irq->start;
platform_set_drvdata(pdev, dev);
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index b7a9977b025f..7f38c01fb3a0 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -196,13 +196,11 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
.getown = pcf_isa_getown,
.getclock = pcf_isa_getclock,
.waitforpin = pcf_isa_waitforpin,
- .udelay = 10,
- .timeout = 100,
};
static struct i2c_adapter pcf_isa_ops = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data,
.name = "i2c-elektor",
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 7c1b762aa681..79b455a1f090 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -140,7 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
adap->owner = THIS_MODULE;
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data;
- adap->class = I2C_CLASS_HWMON;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev;
/*
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index f9972f9651e4..1098f21ace13 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -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
Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org>
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index b0f771fe4326..dc7ea32b69a8 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -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>,
Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
<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
it under the terms of the GNU General Public License as published by
@@ -64,6 +62,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/acpi.h>
#include <asm/io.h>
/* I801 SMBus address offsets */
@@ -121,6 +120,10 @@
#define SMBHSTSTS_INTR 0x02
#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 char i801_original_hstcfg;
static struct pci_driver i801_driver;
@@ -132,105 +135,137 @@ static struct pci_dev *I801_dev;
#define FEATURE_I2C_BLOCK_READ (1 << 3)
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 result = 0;
- int timeout = 0;
+ int status;
- dev_dbg(&I801_dev->dev, "Transaction (pre): 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));
-
- /* Make sure the SMBus host is ready to start transmitting */
- /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
- if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
- dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
- temp);
- outb_p(temp, SMBHSTSTS);
- if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
- dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
- return -1;
- } else {
- dev_dbg(&I801_dev->dev, "Successful!\n");
+ status = inb_p(SMBHSTSTS);
+ if (status & SMBHSTSTS_HOST_BUSY) {
+ dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n");
+ return -EBUSY;
+ }
+
+ status &= STATUS_FLAGS;
+ if (status) {
+ dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n",
+ status);
+ outb_p(status, SMBHSTSTS);
+ status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
+ if (status) {
+ dev_err(&I801_dev->dev,
+ "Failed clearing status flags (%02x)\n",
+ status);
+ return -EBUSY;
}
}
- /* the current contents of SMBHSTCNT can be overwritten, since PEC,
- * INTREN, SMBSCMD are passed in xact */
- outb_p(xact | I801_START, SMBHSTCNT);
+ return 0;
+}
- /* We will always wait for a fraction of a second! */
- do {
- msleep(1);
- temp = inb_p(SMBHSTSTS);
- } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
+/* 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 >= MAX_TIMEOUT) {
- dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
- result = -1;
+ 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);
- }
- if (temp & SMBHSTSTS_FAILED) {
- result = -1;
- dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
+ /* 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 (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 (status & SMBHSTSTS_FAILED) {
+ result = -EIO;
+ dev_err(&I801_dev->dev, "Transaction failed\n");
}
-
- if (temp & SMBHSTSTS_DEV_ERR) {
- result = -1;
- dev_dbg(&I801_dev->dev, "Error: no response!\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 ((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);
+ 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);
+ }
}
- 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;
}
+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,
+ * INTREN, SMBSCMD are passed in xact */
+ outb_p(xact | I801_START, SMBHSTCNT);
+
+ /* We will always wait for a fraction of a second! */
+ do {
+ msleep(1);
+ status = inb_p(SMBHSTSTS);
+ } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
+
+ result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+ if (result < 0)
+ return result;
+
+ outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
+ return 0;
+}
+
/* wait for INTR bit as advised by Intel */
static void i801_wait_hwpec(void)
{
int timeout = 0;
- int temp;
+ int status;
do {
msleep(1);
- temp = inb_p(SMBHSTSTS);
- } while ((!(temp & SMBHSTSTS_INTR))
+ status = inb_p(SMBHSTSTS);
+ } while ((!(status & SMBHSTSTS_INTR))
&& (timeout++ < MAX_TIMEOUT));
if (timeout >= MAX_TIMEOUT) {
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,
char read_write, int hwpec)
{
int i, len;
+ int status;
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);
}
- if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
- I801_PEC_EN * hwpec))
- return -1;
+ status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
+ I801_PEC_EN * hwpec);
+ if (status)
+ return status;
if (read_write == I2C_SMBUS_READ) {
len = inb_p(SMBHSTDAT0);
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
- return -1;
+ return -EPROTO;
data->block[0] = len;
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 smbcmd;
- int temp;
- int result = 0;
+ int status;
+ int result;
int timeout;
- unsigned char errmask;
+
+ result = i801_check_pre();
+ if (result < 0)
+ return result;
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);
- 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)
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;
do {
msleep(1);
- temp = inb_p(SMBHSTSTS);
+ status = inb_p(SMBHSTSTS);
}
- while ((!(temp & SMBHSTSTS_BYTE_DONE))
+ while ((!(status & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_TIMEOUT));
- /* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
- /* 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);
- 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");
- }
+ result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+ if (result < 0)
+ return result;
if (i == 1 && read_write == I2C_SMBUS_READ
&& command != I2C_SMBUS_I2C_BLOCK_DATA) {
len = inb_p(SMBHSTDAT0);
- if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
- return -1;
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
+ 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;
}
@@ -371,30 +367,19 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
data->block[i] = inb_p(SMBBLKDAT);
if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
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) {
- dev_dbg(&I801_dev->dev,
- "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;
+ /* signals SMBBLKDAT ready */
+ outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS);
}
- return result;
+
+ return 0;
}
static int i801_set_block_buffer_mode(void)
{
outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
- return -1;
+ return -EIO;
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)) {
dev_err(&I801_dev->dev,
"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 -1 on error. */
+/* Return negative errno on error. */
static s32 i801_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command,
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);
block = 1;
break;
- case I2C_SMBUS_PROC_CALL:
default:
dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
- return -1;
+ return -EOPNOTSUPP;
}
if (hwpec) /* enable/disable hardware PEC */
@@ -537,7 +521,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
if(block)
return ret;
if(ret)
- return -1;
+ return ret;
if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
return 0;
@@ -572,7 +556,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_I801,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -639,6 +623,10 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
goto exit;
}
+ err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
+ if (err)
+ goto exit;
+
err = pci_request_region(dev, SMBBAR, i801_driver.name);
if (err) {
dev_err(&dev->dev, "Failed to request SMBus region "
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
deleted file mode 100644
index 42e8d94c276f..000000000000
--- a/drivers/i2c/busses/i2c-i810.c
+++ /dev/null
@@ -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);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 85dbf34382e1..070f078b5f5c 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -42,13 +42,7 @@
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
-
-#ifdef CONFIG_IBM_OCP
-#include <asm/ocp.h>
-#include <asm/ibm4xx.h>
-#else
#include <linux/of_platform.h>
-#endif
#include "i2c-ibm_iic.h"
@@ -665,180 +659,6 @@ static inline u8 iic_clckdiv(unsigned int opb)
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,
struct ibm_iic_private *dev)
{
@@ -934,7 +754,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
- adap->class = I2C_CLASS_HWMON;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &iic_algo;
adap->timeout = 1;
adap->nr = dev->idx;
@@ -987,11 +807,7 @@ static int __devexit iic_remove(struct of_device *ofdev)
}
static const struct of_device_id ibm_iic_match[] = {
- { .compatible = "ibm,iic-405ex", },
- { .compatible = "ibm,iic-405gp", },
- { .compatible = "ibm,iic-440gp", },
- { .compatible = "ibm,iic-440gpx", },
- { .compatible = "ibm,iic-440grx", },
+ { .compatible = "ibm,iic", },
{}
};
@@ -1011,7 +827,6 @@ static void __exit iic_exit(void)
{
of_unregister_platform_driver(&ibm_iic_driver);
}
-#endif /* CONFIG_IBM_OCP */
module_init(iic_init);
module_exit(iic_exit);
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 39884e797594..fc2714ac0c0f 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -482,7 +482,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
new_adapter->id = I2C_HW_IOP3XX;
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->nr = pdev->id;
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
new file mode 100644
index 000000000000..b9c01aa90036
--- /dev/null
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -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);
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a076129de7e8..10b9342a36c2 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = {
.name = "MPC adapter",
.id = I2C_HW_MPC107,
.algo = &mpc_algo,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.timeout = 1,
};
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 036e6a883e67..9e8118d2fe64 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -530,7 +530,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
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.nr = pd->id;
platform_set_drvdata(pd, drv_data);
diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c
new file mode 100644
index 000000000000..6a8995dfd0bb
--- /dev/null
+++ b/drivers/i2c/busses/i2c-nforce2-s4985.c
@@ -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);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 43c9f8df9509..3b19bc41a60b 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -51,6 +51,7 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/dmi.h>
+#include <linux/acpi.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
@@ -124,6 +125,20 @@ static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
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)
{
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");
if (smbus->can_abort)
nforce2_abort(adap);
- return -1;
+ return -ETIMEDOUT;
}
if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp);
- return -1;
+ return -EIO;
}
return 0;
}
-/* Return -1 on error */
+/* Return negative errno on error */
static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write,
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;
unsigned char protocol, pec;
u8 len;
- int i;
+ int i, status;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
NVIDIA_SMB_PRTCL_WRITE;
@@ -219,7 +234,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
"Transaction failed "
"(requested block size: %d)\n",
len);
- return -1;
+ return -EINVAL;
}
outb_p(len, NVIDIA_SMB_BCNT);
for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
@@ -231,14 +246,15 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
- return -1;
+ return -EOPNOTSUPP;
}
outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
outb_p(protocol, NVIDIA_SMB_PRTCL);
- if (nforce2_check_status(adap))
- return -1;
+ status = nforce2_check_status(adap);
+ if (status)
+ return status;
if (read_write == I2C_SMBUS_WRITE)
return 0;
@@ -260,7 +276,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
dev_err(&adap->dev, "Transaction failed "
"(received block size: 0x%02x)\n",
len);
- return -1;
+ return -EPROTO;
}
for (i = 0; i < len; 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) {
dev_err(&dev->dev, "Error reading PCI config for %s\n",
name);
- return -1;
+ return -EIO;
}
smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
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)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
smbus->base, smbus->base+smbus->size-1, name);
- return -1;
+ return -EBUSY;
}
smbus->adapter.owner = THIS_MODULE;
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_data = smbus;
smbus->adapter.dev.parent = &dev->dev;
@@ -346,7 +367,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
if (error) {
dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
release_region(smbus->base, smbus->size);
- return -1;
+ return error;
}
dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base);
return 0;
@@ -398,6 +419,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
return -ENODEV;
}
+ nforce2_set_reference(&smbuses[0].adapter);
return 0;
}
@@ -406,6 +428,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
{
struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
+ nforce2_set_reference(NULL);
if (smbuses[0].base) {
i2c_del_adapter(&smbuses[0].adapter);
release_region(smbuses[0].base, smbuses[0].size);
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index f145692cbb76..e5193bf75483 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -29,6 +29,7 @@ struct ocores_i2c {
int pos;
int nmsgs;
int state; /* see STATE_ */
+ int clock_khz;
};
/* registers */
@@ -173,8 +174,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
return -ETIMEDOUT;
}
-static void ocores_init(struct ocores_i2c *i2c,
- struct ocores_i2c_platform_data *pdata)
+static void ocores_init(struct ocores_i2c *i2c)
{
int prescale;
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 */
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_PREHIGH, prescale >> 8);
@@ -205,7 +205,7 @@ static const struct i2c_algorithm ocores_algorithm = {
static struct i2c_adapter ocores_adapter = {
.owner = THIS_MODULE,
.name = "i2c-ocores",
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ocores_algorithm,
};
@@ -248,7 +248,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
}
i2c->regstep = pdata->regstep;
- ocores_init(i2c, pdata);
+ i2c->clock_khz = pdata->clock_khz;
+ ocores_init(i2c);
init_waitqueue_head(&i2c->wait);
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;
}
+#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 */
MODULE_ALIAS("platform:ocores-i2c");
static struct platform_driver ocores_i2c_driver = {
- .probe = ocores_i2c_probe,
- .remove = __devexit_p(ocores_i2c_remove),
- .driver = {
+ .probe = ocores_i2c_probe,
+ .remove = __devexit_p(ocores_i2c_remove),
+ .suspend = ocores_i2c_suspend,
+ .resume = ocores_i2c_resume,
+ .driver = {
.owner = THIS_MODULE,
.name = "ocores-i2c",
},
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 1603c81e39d4..adf0fbb902f0 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -365,7 +365,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"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_data = smbus;
smbus->adapter.nr = PCI_FUNC(dev->devfn);
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index 9d75f51e8f0e..6bb15ad0a6b6 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -163,7 +163,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
i2c->reg_base = ioremap(res->start, res_len(res));
if (!i2c->reg_base) {
- ret = -EIO;
+ ret = -ENOMEM;
goto e_remap;
}
i2c->io_base = res->start;
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index ac9165968587..eaa9b387543e 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -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
Philip Edelbrock <phil@netroedge.com>
@@ -39,16 +37,10 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/dmi.h>
+#include <linux/acpi.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 */
#define SMBHSTSTS (0 + piix4_smba)
#define SMBHSLVSTS (1 + piix4_smba)
@@ -101,8 +93,6 @@ MODULE_PARM_DESC(force_addr,
"Forcibly enable the PIIX4 at the given address. "
"EXTREMELY DANGEROUS!");
-static int piix4_transaction(void);
-
static unsigned short piix4_smba;
static int srvrworks_csb5_delay;
static struct pci_driver piix4_driver;
@@ -141,8 +131,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
{
unsigned char temp;
- dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
-
if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
(PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5))
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);
piix4_smba &= 0xfff0;
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 "
"force_addr=0xaddr\n");
return -ENODEV;
}
}
+ if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
+ return -EBUSY;
+
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);
- return -ENODEV;
+ return -EBUSY;
}
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");
pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
- dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp);
- dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba);
+ dev_info(&PIIX4_dev->dev,
+ "SMBus Host Controller at 0x%x, revision %d\n",
+ piix4_smba, temp);
return 0;
}
-/* Another internally used function */
static int piix4_transaction(void)
{
int temp;
@@ -253,7 +244,7 @@ static int piix4_transaction(void)
outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
- return -1;
+ return -EBUSY;
} else {
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 (timeout >= MAX_TIMEOUT) {
dev_err(&piix4_adapter.dev, "SMBus Timeout!\n");
- result = -1;
+ result = -ETIMEDOUT;
}
if (temp & 0x10) {
- result = -1;
+ result = -EIO;
dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n");
}
if (temp & 0x08) {
- result = -1;
+ result = -EIO;
dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
}
if (temp & 0x04) {
- result = -1;
+ result = -ENXIO;
dev_dbg(&piix4_adapter.dev, "Error: no response!\n");
}
@@ -309,31 +300,29 @@ static int piix4_transaction(void)
return result;
}
-/* Return -1 on error. */
+/* Return negative errno on error. */
static s32 piix4_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;
+ int status;
switch (size) {
- case I2C_SMBUS_PROC_CALL:
- dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
- return -1;
case I2C_SMBUS_QUICK:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ outb_p((addr << 1) | read_write,
SMBHSTADD);
size = PIIX4_QUICK;
break;
case I2C_SMBUS_BYTE:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ outb_p((addr << 1) | read_write,
SMBHSTADD);
if (read_write == I2C_SMBUS_WRITE)
outb_p(command, SMBHSTCMD);
size = PIIX4_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ outb_p((addr << 1) | read_write,
SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE)
@@ -341,7 +330,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
size = PIIX4_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ outb_p((addr << 1) | read_write,
SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
@@ -351,15 +340,13 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
size = PIIX4_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ outb_p((addr << 1) | read_write,
SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0];
- if (len < 0)
- len = 0;
- if (len > 32)
- len = 32;
+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
outb_p(len, SMBHSTDAT0);
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++)
@@ -367,12 +354,16 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
}
size = PIIX4_BLOCK_DATA;
break;
+ default:
+ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
}
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
- if (piix4_transaction()) /* Error in transaction */
- return -1;
+ status = piix4_transaction();
+ if (status)
+ return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
return 0;
@@ -388,6 +379,8 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
break;
case PIIX4_BLOCK_DATA:
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 */
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT);
@@ -411,7 +404,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_PIIX4,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 63b3e2c11cff..dcf2045b5222 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -622,7 +622,7 @@ static struct i2c_algorithm pmcmsptwi_algo = {
static struct i2c_adapter pmcmsptwi_adapter = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &pmcmsptwi_algo,
.name = DRV_NAME,
};
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
deleted file mode 100644
index 07c1f1e27df1..000000000000
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ /dev/null
@@ -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);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index eb69fbadc9cb..78c0fc42bc73 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1134,5 +1134,5 @@ static void __exit i2c_adap_pxa_exit(void)
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pxa2xx-i2c");
-module_init(i2c_adap_pxa_init);
+subsys_initcall(i2c_adap_pxa_init);
module_exit(i2c_adap_pxa_exit);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 1305ef190fc1..fd7b2308a0b3 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -591,7 +591,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
.owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm,
.retries = 2,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
},
};
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
deleted file mode 100644
index 8adf4abaa035..000000000000
--- a/drivers/i2c/busses/i2c-savage4.c
+++ /dev/null
@@ -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);
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 114634da6c6e..4ddefbf238e9 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -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(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,
.id = I2C_HW_SIBYTE,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL,
.algo_data = &sibyte_board_data[0],
+ .nr = 0,
.name = "SiByte SMBus 0",
},
{
.owner = THIS_MODULE,
.id = I2C_HW_SIBYTE,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL,
.algo_data = &sibyte_board_data[1],
+ .nr = 1,
.name = "SiByte SMBus 1",
},
};
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 9ca8f9155f95..dfc2d5eb6a68 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -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
Philip Edelbrock <phil@netroedge.com>
@@ -62,6 +60,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/acpi.h>
#include <asm/io.h>
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
* 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,
sis5595_driver.name)) {
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);
if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
- return -1;
+ return -EBUSY;
} else {
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 (timeout >= MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
- result = -1;
+ result = -ETIMEDOUT;
}
if (temp & 0x10) {
dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
- result = -1;
+ result = -ENXIO;
}
if (temp & 0x20) {
dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
"next hard reset (or not...)\n");
/* 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);
@@ -282,11 +286,13 @@ static int sis5595_transaction(struct i2c_adapter *adap)
return result;
}
-/* Return -1 on error. */
+/* Return negative errno on error. */
static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
+ int status;
+
switch (size) {
case I2C_SMBUS_QUICK:
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;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
- return -1;
+ return -EOPNOTSUPP;
}
sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
- if (sis5595_transaction(adap))
- return -1;
+ status = sis5595_transaction(adap);
+ if (status)
+ return status;
if ((size != SIS5595_PROC_CALL) &&
((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 = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_SIS5595,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 3765dd7f450f..e7c4b790da54 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -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>
This program is free software; you can redistribute it and/or modify
@@ -55,6 +52,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/acpi.h>
#include <asm/io.h>
/* 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) {
dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
- return -1;
+ return -EBUSY;
} else {
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 (timeout >= MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
- result = -1;
+ result = -ETIMEDOUT;
}
if (temp & 0x02) {
dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
- result = -1;
+ result = -ENXIO;
}
if (temp & 0x04) {
dev_err(&adap->dev, "Bus collision!\n");
- result = -1;
+ result = -EIO;
/*
TBD: Datasheet say:
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)) {
dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
/* first transaction */
- if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock))
- return -1;
+ rc = sis630_transaction_start(adap,
+ SIS630_BLOCK_DATA, &oldclock);
+ if (rc)
+ return rc;
}
else if ((i-1)%8 == 7 || i==len) {
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);
}
- 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");
- rc = -1;
break;
}
}
@@ -275,13 +276,14 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
else {
/* read request */
data->block[0] = len = 0;
- if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) {
- return -1;
- }
+ rc = sis630_transaction_start(adap,
+ SIS630_BLOCK_DATA, &oldclock);
+ if (rc)
+ return rc;
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");
- rc = -1;
break;
}
/* 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 -1 on error. */
+/* Return negative errno on error. */
static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
+ int status;
+
switch (size) {
case I2C_SMBUS_QUICK:
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;
return sis630_block_data(adap, data, read_write);
default:
- printk("Unsupported I2C size\n");
- return -1;
- break;
+ dev_warn(&adap->dev, "Unsupported transaction %d\n",
+ size);
+ return -EOPNOTSUPP;
}
- if (sis630_transaction(adap, size))
- return -1;
+ status = sis630_transaction(adap, size);
+ if (status)
+ return status;
if ((size != SIS630_PCALL) &&
((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:
data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
break;
- default:
- return -1;
- break;
}
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);
+ 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. */
if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name)) {
@@ -458,7 +465,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_SIS630,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index dc235bb8e24d..f1bba6396641 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -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>
This program is free software; you can redistribute it and/or modify
@@ -40,6 +37,7 @@
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#include <asm/io.h>
/* base address register in PCI config space */
@@ -111,7 +109,7 @@ static int sis96x_transaction(int size)
/* check it again */
if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {
dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp);
- return -1;
+ return -EBUSY;
} else {
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 (timeout >= MAX_TIMEOUT) {
dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
- result = -1;
+ result = -ETIMEDOUT;
}
/* device error - probably missing ACK */
if (temp & 0x02) {
dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n");
- result = -1;
+ result = -ENXIO;
}
/* bus collision */
if (temp & 0x04) {
dev_dbg(&sis96x_adapter.dev, "Bus collision!\n");
- result = -1;
+ result = -EIO;
}
/* Finish up by resetting the bus */
@@ -161,11 +159,12 @@ static int sis96x_transaction(int size)
return result;
}
-/* Return -1 on error. */
+/* Return negative errno on error. */
static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data)
{
+ int status;
switch (size) {
case I2C_SMBUS_QUICK:
@@ -200,20 +199,14 @@ static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
SIS96x_PROC_CALL : SIS96x_WORD_DATA);
break;
- case I2C_SMBUS_BLOCK_DATA:
- /* TO DO: */
- dev_info(&adap->dev, "SMBus block not implemented!\n");
- return -1;
- break;
-
default:
- dev_info(&adap->dev, "Unsupported I2C size\n");
- return -1;
- break;
+ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
}
- if (sis96x_transaction(size))
- return -1;
+ status = sis96x_transaction(size);
+ if (status)
+ return status;
if ((size != SIS96x_PROC_CALL) &&
((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 = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_SIS96X,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.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",
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. */
if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
sis96x_driver.name)) {
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index d08eeec53913..1b7b2af94036 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -43,7 +43,7 @@ struct stub_chip {
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,
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:
dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
- ret = -1;
+ ret = -EOPNOTSUPP;
break;
} /* switch (size) */
@@ -140,7 +140,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter stub_adapter = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
.name = "SMBus stub driver",
};
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
index de9db49e54d9..224aa12ee7c8 100644
--- a/drivers/i2c/busses/i2c-taos-evm.c
+++ b/drivers/i2c/busses/i2c-taos-evm.c
@@ -96,9 +96,8 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
sprintf(p, "$%02X", command);
break;
default:
- dev_dbg(&adapter->dev, "Unsupported transaction size %d\n",
- size);
- return -EINVAL;
+ dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
}
/* Send the transaction to the TAOS EVM */
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 61716f6b14dc..29cef0433f34 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -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
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 = {
.owner = THIS_MODULE,
.id = I2C_HW_B_VIA,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.name = "VIA i2c",
.algo_data = &bit_data,
};
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 77b13d027f86..862eb352a2d9 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -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>,
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -50,6 +48,7 @@
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static struct pci_dev *vt596_pdev;
@@ -152,7 +151,7 @@ static int vt596_transaction(u8 size)
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_err(&vt596_adapter.dev, "SMBus reset failed! "
"(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 (timeout >= MAX_TIMEOUT) {
- result = -1;
+ result = -ETIMEDOUT;
dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
}
if (temp & 0x10) {
- result = -1;
+ result = -EIO;
dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
size);
}
if (temp & 0x08) {
- result = -1;
+ result = -EIO;
dev_err(&vt596_adapter.dev, "SMBus collision!\n");
}
if (temp & 0x04) {
int read = inb_p(SMBHSTADD) & 0x01;
- result = -1;
+ result = -ENXIO;
/* The quick and receive byte commands are used to probe
for chips, so errors are expected, and we don't want
to frighten the user. */
@@ -202,12 +201,13 @@ static int vt596_transaction(u8 size)
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,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data)
{
int i;
+ int status;
switch (size) {
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);
- if (vt596_transaction(size)) /* Error in transaction */
- return -1;
+ status = vt596_transaction(size);
+ if (status)
+ return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
return 0;
@@ -285,9 +286,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
return 0;
exit_unsupported:
- dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
+ dev_warn(&vt596_adapter.dev, "Unsupported transaction %d\n",
size);
- return -1;
+ return -EOPNOTSUPP;
}
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 = {
.owner = THIS_MODULE,
.id = I2C_HW_SMBUS_VIA2,
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -354,6 +355,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
}
found:
+ error = acpi_check_region(vt596_smba, 8, vt596_driver.name);
+ if (error)
+ return error;
+
if (!request_region(vt596_smba, 8, vt596_driver.name)) {
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
vt596_smba);
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 88a3447e11e1..1d4ae26ba73d 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -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>,
Philip Edelbrock <phil@netroedge.com>,
Ralph Metzler <rjkm@thp.uni-koeln.de>, and
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 61abe0f33255..ed794b145a11 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -442,7 +442,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
adapter->owner = THIS_MODULE;
adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm;
- adapter->class = I2C_CLASS_HWMON;
+ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adapter->dev.parent = dev;
mutex_init(&iface->mutex);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 2da2edfa68ec..6326468d5f0b 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -26,8 +26,8 @@ config SENSORS_EEPROM
will be called eeprom.
config SENSORS_PCF8574
- tristate "Philips PCF8574 and PCF8574A"
- depends on EXPERIMENTAL
+ tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
+ depends on EXPERIMENTAL && GPIO_PCF857X = "n"
default n
help
If you say yes here you get support for Philips PCF8574 and
@@ -36,12 +36,16 @@ config SENSORS_PCF8574
This driver can also be built as a module. If so, the module
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
hardware. If unsure, say N.
config PCF8575
- tristate "Philips PCF8575"
+ tristate "Philips PCF8575 (DEPRECATED)"
default n
+ depends on GPIO_PCF857X = "n"
help
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
@@ -50,12 +54,15 @@ config PCF8575
This driver can also be built as a module. If so, the module
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
hardware. If unsure, say N.
config SENSORS_PCA9539
tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)"
- depends on EXPERIMENTAL && GPIO_PCA9539 = "n"
+ depends on EXPERIMENTAL && GPIO_PCA953X = "n"
help
If you say yes here you get support for the Philips PCA9539
16-bit I/O port.
@@ -64,7 +71,7 @@ config SENSORS_PCA9539
will be called pca9539.
This driver is deprecated and will be dropped soon. Use
- drivers/gpio/pca9539.c instead.
+ drivers/gpio/pca953x.c instead.
config SENSORS_PCF8591
tristate "Philips PCF8591"
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 7dee001e5133..fc17c4de7c21 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -1,6 +1,4 @@
/*
- eeprom.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com>
Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
@@ -53,7 +51,6 @@ enum eeprom_nature {
/* Each client has this additional data */
struct eeprom_data {
- struct i2c_client client;
struct mutex update_lock;
u8 valid; /* bitfield, bit!=0 if slice is valid */
unsigned long last_updated[8]; /* In jiffies, 8 slices */
@@ -62,23 +59,34 @@ struct eeprom_data {
};
-static int eeprom_attach_adapter(struct i2c_adapter *adapter);
-static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
-static int eeprom_detach_client(struct i2c_client *client);
+static int eeprom_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int eeprom_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int eeprom_remove(struct i2c_client *client);
+
+static struct i2c_device_id eeprom_id[] = {
+ { "eeprom", 0 },
+ { }
+};
/* This is the driver that will be inserted */
static struct i2c_driver eeprom_driver = {
+ .class = I2C_CLASS_DDC | I2C_CLASS_SPD,
.driver = {
.name = "eeprom",
},
- .attach_adapter = eeprom_attach_adapter,
- .detach_client = eeprom_detach_client,
+ .probe = eeprom_probe,
+ .remove = eeprom_remove,
+ .detect = eeprom_detect,
+ .id_table = eeprom_id,
+ .address_data = &addr_data,
};
static void eeprom_update_client(struct i2c_client *client, u8 slice)
{
struct eeprom_data *data = i2c_get_clientdata(client);
- int i, j;
+ int i;
mutex_lock(&data->update_lock);
@@ -93,15 +101,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
!= 32)
goto exit;
} else {
- if (i2c_smbus_write_byte(client, slice << 5)) {
- dev_dbg(&client->dev, "eeprom read start has failed!\n");
- goto exit;
- }
- for (i = slice << 5; i < (slice + 1) << 5; i++) {
- j = i2c_smbus_read_byte(client);
- if (j < 0)
+ for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
+ int word = i2c_smbus_read_word_data(client, i);
+ if (word < 0)
goto exit;
- data->data[i] = (u8) j;
+ data->data[i] = word & 0xff;
+ data->data[i + 1] = word >> 8;
}
}
data->last_updated[slice] = jiffies;
@@ -157,93 +162,85 @@ static struct bin_attribute eeprom_attr = {
.read = eeprom_read,
};
-static int eeprom_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int eeprom_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- return i2c_probe(adapter, &addr_data, eeprom_detect);
+ struct i2c_adapter *adapter = client->adapter;
+
+ /* 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) && client->addr >= 0x51)
+ return -ENODEV;
+
+ /* There are four ways we can read the EEPROM data:
+ (1) I2C block reads (faster, but unsupported by most adapters)
+ (2) Word reads (128% overhead)
+ (3) Consecutive byte reads (88% overhead, unsafe)
+ (4) Regular byte data reads (265% overhead)
+ The third and fourth methods are not implemented by this driver
+ because all known adapters support one of the first two. */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
+ && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+ return -ENODEV;
+
+ strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
+
+ return 0;
}
-/* This function is called by i2c_probe */
-static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
+static int eeprom_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *new_client;
+ struct i2c_adapter *adapter = client->adapter;
struct eeprom_data *data;
- int err = 0;
-
- /* There are three ways we can read the EEPROM data:
- (1) I2C block reads (faster, but unsupported by most adapters)
- (2) Consecutive byte reads (100% overhead)
- (3) Regular byte data reads (200% overhead)
- The third method is not implemented by this driver because all
- known adapters support at least the second. */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA
- | I2C_FUNC_SMBUS_BYTE))
- goto exit;
+ int err;
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- new_client = &data->client;
memset(data->data, 0xff, EEPROM_SIZE);
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &eeprom_driver;
- new_client->flags = 0;
-
- /* Fill in the remaining client fields */
- strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE);
- data->valid = 0;
+ i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
data->nature = UNKNOWN;
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_kfree;
-
/* Detect the Vaio nature of EEPROMs.
We use the "PCG-" or "VGN-" prefix as the signature. */
- if (address == 0x57) {
+ if (client->addr == 0x57
+ && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
char name[4];
- name[0] = i2c_smbus_read_byte_data(new_client, 0x80);
- name[1] = i2c_smbus_read_byte(new_client);
- name[2] = i2c_smbus_read_byte(new_client);
- name[3] = i2c_smbus_read_byte(new_client);
+ name[0] = i2c_smbus_read_byte_data(client, 0x80);
+ name[1] = i2c_smbus_read_byte_data(client, 0x81);
+ name[2] = i2c_smbus_read_byte_data(client, 0x82);
+ name[3] = i2c_smbus_read_byte_data(client, 0x83);
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");
data->nature = VAIO;
}
}
/* 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)
- goto exit_detach;
+ goto exit_kfree;
return 0;
-exit_detach:
- i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
return err;
}
-static int eeprom_detach_client(struct i2c_client *client)
+static int eeprom_remove(struct i2c_client *client)
{
- int err;
-
sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
-
- err = i2c_detach_client(client);
- if (err)
- return err;
-
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index b1b45dddb17e..d21cb32449e2 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -49,10 +49,9 @@ MODULE_LICENSE("GPL");
struct isp1301 {
struct otg_transceiver otg;
- struct i2c_client client;
+ struct i2c_client *client;
void (*i2c_release)(struct device *dev);
- int irq;
int irq_type;
u32 last_otg_ctrl;
@@ -138,14 +137,6 @@ static inline void notresponding(struct isp1301 *isp)
/*-------------------------------------------------------------------------*/
-/* only two addresses possible */
-#define ISP_BASE 0x2c
-static unsigned short normal_i2c[] = {
- ISP_BASE, ISP_BASE + 1,
- I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
static struct i2c_driver isp1301_driver;
/* smbus apis are used for portability */
@@ -153,25 +144,25 @@ static struct i2c_driver isp1301_driver;
static inline u8
isp1301_get_u8(struct isp1301 *isp, u8 reg)
{
- return i2c_smbus_read_byte_data(&isp->client, reg + 0);
+ return i2c_smbus_read_byte_data(isp->client, reg + 0);
}
static inline int
isp1301_get_u16(struct isp1301 *isp, u8 reg)
{
- return i2c_smbus_read_word_data(&isp->client, reg);
+ return i2c_smbus_read_word_data(isp->client, reg);
}
static inline int
isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
{
- return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits);
+ return i2c_smbus_write_byte_data(isp->client, reg + 0, bits);
}
static inline int
isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
{
- return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits);
+ return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
}
/*-------------------------------------------------------------------------*/
@@ -349,10 +340,10 @@ isp1301_defer_work(struct isp1301 *isp, int work)
int status;
if (isp && !test_and_set_bit(work, &isp->todo)) {
- (void) get_device(&isp->client.dev);
+ (void) get_device(&isp->client->dev);
status = schedule_work(&isp->work);
if (!status && !isp->working)
- dev_vdbg(&isp->client.dev,
+ dev_vdbg(&isp->client->dev,
"work item %d may be lost\n", work);
}
}
@@ -1107,7 +1098,7 @@ isp1301_work(struct work_struct *work)
/* transfer state from otg engine to isp1301 */
if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
otg_update_isp(isp);
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
#endif
/* transfer state from isp1301 to otg engine */
@@ -1115,7 +1106,7 @@ isp1301_work(struct work_struct *work)
u8 stat = isp1301_clear_latch(isp);
isp_update_otg(isp, stat);
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
@@ -1150,7 +1141,7 @@ isp1301_work(struct work_struct *work)
}
host_resume(isp);
// mdelay(10);
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
@@ -1159,15 +1150,15 @@ isp1301_work(struct work_struct *work)
if (!stop)
mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
#endif
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
if (isp->todo)
- dev_vdbg(&isp->client.dev,
+ dev_vdbg(&isp->client->dev,
"work done, todo = 0x%lx\n",
isp->todo);
if (stop) {
- dev_dbg(&isp->client.dev, "stop\n");
+ dev_dbg(&isp->client->dev, "stop\n");
break;
}
} while (isp->todo);
@@ -1191,7 +1182,7 @@ static void isp1301_release(struct device *dev)
{
struct isp1301 *isp;
- isp = container_of(dev, struct isp1301, client.dev);
+ isp = device_get_drvdata(dev);
/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
if (isp->i2c_release)
@@ -1201,15 +1192,15 @@ static void isp1301_release(struct device *dev)
static struct isp1301 *the_transceiver;
-static int isp1301_detach_client(struct i2c_client *i2c)
+static int __exit isp1301_remove(struct i2c_client *i2c)
{
struct isp1301 *isp;
- isp = container_of(i2c, struct isp1301, client);
+ isp = i2c_get_clientdata(i2c);
isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
- free_irq(isp->irq, isp);
+ free_irq(i2c->irq, isp);
#ifdef CONFIG_USB_OTG
otg_unbind(isp);
#endif
@@ -1224,7 +1215,7 @@ static int isp1301_detach_client(struct i2c_client *i2c)
put_device(&i2c->dev);
the_transceiver = 0;
- return i2c_detach_client(i2c);
+ return 0;
}
/*-------------------------------------------------------------------------*/
@@ -1257,7 +1248,7 @@ static int isp1301_otg_enable(struct isp1301 *isp)
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
- dev_info(&isp->client.dev, "ready for dual-role USB ...\n");
+ dev_info(&isp->client->dev, "ready for dual-role USB ...\n");
return 0;
}
@@ -1282,7 +1273,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
#ifdef CONFIG_USB_OTG
isp->otg.host = host;
- dev_dbg(&isp->client.dev, "registered host\n");
+ dev_dbg(&isp->client->dev, "registered host\n");
host_suspend(isp);
if (isp->otg.gadget)
return isp1301_otg_enable(isp);
@@ -1297,7 +1288,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
if (machine_is_omap_h2())
isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
- dev_info(&isp->client.dev, "A-Host sessions ok\n");
+ dev_info(&isp->client->dev, "A-Host sessions ok\n");
isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
INTR_ID_GND);
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
@@ -1315,7 +1306,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
return 0;
#else
- dev_dbg(&isp->client.dev, "host sessions not allowed\n");
+ dev_dbg(&isp->client->dev, "host sessions not allowed\n");
return -EINVAL;
#endif
@@ -1341,7 +1332,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
#ifdef CONFIG_USB_OTG
isp->otg.gadget = gadget;
- dev_dbg(&isp->client.dev, "registered gadget\n");
+ dev_dbg(&isp->client->dev, "registered gadget\n");
/* gadget driver may be suspended until vbus_connect () */
if (isp->otg.host)
return isp1301_otg_enable(isp);
@@ -1364,7 +1355,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
INTR_SESS_VLD);
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
INTR_VBUS_VLD);
- dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+ dev_info(&isp->client->dev, "B-Peripheral sessions ok\n");
dump_regs(isp, __func__);
/* If this has a Mini-AB connector, this mode is highly
@@ -1377,7 +1368,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
return 0;
#else
- dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n");
+ dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n");
return -EINVAL;
#endif
}
@@ -1473,12 +1464,10 @@ isp1301_start_hnp(struct otg_transceiver *dev)
/*-------------------------------------------------------------------------*/
-/* no error returns, they'd just make bus scanning stop */
-static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
+static int __init isp1301_probe(struct i2c_client *i2c)
{
int status;
struct isp1301 *isp;
- struct i2c_client *i2c;
if (the_transceiver)
return 0;
@@ -1492,37 +1481,19 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
isp->timer.function = isp1301_timer;
isp->timer.data = (unsigned long) isp;
- isp->irq = -1;
- isp->client.addr = address;
- i2c_set_clientdata(&isp->client, isp);
- isp->client.adapter = bus;
- isp->client.driver = &isp1301_driver;
- strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
- i2c = &isp->client;
-
- /* if this is a true probe, verify the chip ... */
- if (kind < 0) {
- status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
- if (status != I2C_VENDOR_ID_PHILIPS) {
- dev_dbg(&bus->dev, "addr %d not philips id: %d\n",
- address, status);
- goto fail1;
- }
- status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
- if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
- dev_dbg(&bus->dev, "%d not isp1301, %d\n",
- address, status);
- goto fail1;
- }
- }
+ i2c_set_clientdata(i2c, isp);
+ isp->client = i2c;
- status = i2c_attach_client(i2c);
- if (status < 0) {
- dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
- DRIVER_NAME, address, status);
-fail1:
- kfree(isp);
- return 0;
+ /* verify the chip (shouldn't be necesary) */
+ status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
+ if (status != I2C_VENDOR_ID_PHILIPS) {
+ dev_dbg(&i2c->dev, "not philips id: %d\n", status);
+ goto fail;
+ }
+ status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
+ if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
+ dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
+ goto fail;
}
isp->i2c_release = i2c->dev.release;
i2c->dev.release = isp1301_release;
@@ -1551,7 +1522,7 @@ fail1:
status = otg_bind(isp);
if (status < 0) {
dev_dbg(&i2c->dev, "can't bind OTG\n");
- goto fail2;
+ goto fail;
}
#endif
@@ -1564,26 +1535,21 @@ fail1:
/* IRQ wired at M14 */
omap_cfg_reg(M14_1510_GPIO2);
- isp->irq = OMAP_GPIO_IRQ(2);
if (gpio_request(2, "isp1301") == 0)
gpio_direction_input(2);
isp->irq_type = IRQF_TRIGGER_FALLING;
}
isp->irq_type |= IRQF_SAMPLE_RANDOM;
- status = request_irq(isp->irq, isp1301_irq,
+ status = request_irq(i2c->irq, isp1301_irq,
isp->irq_type, DRIVER_NAME, isp);
if (status < 0) {
dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
- isp->irq, status);
-#ifdef CONFIG_USB_OTG
-fail2:
-#endif
- i2c_detach_client(i2c);
- goto fail1;
+ i2c->irq, status);
+ goto fail;
}
- isp->otg.dev = &isp->client.dev;
+ isp->otg.dev = &i2c->dev;
isp->otg.label = DRIVER_NAME;
isp->otg.set_host = isp1301_set_host,
@@ -1614,22 +1580,25 @@ fail2:
status);
return 0;
-}
-static int isp1301_scan_bus(struct i2c_adapter *bus)
-{
- if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA
- | I2C_FUNC_SMBUS_READ_WORD_DATA))
- return -EINVAL;
- return i2c_probe(bus, &addr_data, isp1301_probe);
+fail:
+ kfree(isp);
+ return -ENODEV;
}
+static struct i2c_device_id isp1301_id[] = {
+ { "isp1301_omap", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, isp1301_id);
+
static struct i2c_driver isp1301_driver = {
.driver = {
.name = "isp1301_omap",
},
- .attach_adapter = isp1301_scan_bus,
- .detach_client = isp1301_detach_client,
+ .probe = isp1301_probe,
+ .remove = __exit_p(isp1301_remove),
+ .id_table = isp1301_id,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index cf507b3f60f3..d8dd3649f8a4 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -53,7 +53,7 @@ I2C_CLIENT_INSMOD_1(max6875);
/* Each client has this additional data */
struct max6875_data {
- struct i2c_client client;
+ struct i2c_client *fake_client;
struct mutex update_lock;
u32 valid;
@@ -61,17 +61,27 @@ struct max6875_data {
unsigned long last_updated[USER_EEPROM_SLICES];
};
-static int max6875_attach_adapter(struct i2c_adapter *adapter);
-static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
-static int max6875_detach_client(struct i2c_client *client);
+static int max6875_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int max6875_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int max6875_remove(struct i2c_client *client);
+
+static struct i2c_device_id max6875_id[] = {
+ { "max6875", 0 },
+ { }
+};
/* This is the driver that will be inserted */
static struct i2c_driver max6875_driver = {
.driver = {
.name = "max6875",
},
- .attach_adapter = max6875_attach_adapter,
- .detach_client = max6875_detach_client,
+ .probe = max6875_probe,
+ .remove = max6875_remove,
+ .id_table = max6875_id,
+ .detect = max6875_detect,
+ .address_data = &addr_data,
};
static void max6875_update_slice(struct i2c_client *client, int slice)
@@ -159,95 +169,67 @@ static struct bin_attribute user_eeprom_attr = {
.read = max6875_read,
};
-static int max6875_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_probe(adapter, &addr_data, max6875_detect);
-}
-
-/* This function is called by i2c_probe */
-static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max6875_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *real_client;
- struct i2c_client *fake_client;
- struct max6875_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
| I2C_FUNC_SMBUS_READ_BYTE))
- return 0;
+ return -ENODEV;
/* Only check even addresses */
- if (address & 1)
- return 0;
+ if (client->addr & 1)
+ return -ENODEV;
+
+ strlcpy(info->type, "max6875", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int max6875_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max6875_data *data;
+ int err;
if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
return -ENOMEM;
/* A fake client is created on the odd address */
- if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
+ if (!data->fake_client) {
err = -ENOMEM;
- goto exit_kfree1;
+ goto exit_kfree;
}
/* Init real i2c_client */
- real_client = &data->client;
- i2c_set_clientdata(real_client, data);
- real_client->addr = address;
- real_client->adapter = adapter;
- real_client->driver = &max6875_driver;
- real_client->flags = 0;
- strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
+ i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
- /* Init fake client data */
- i2c_set_clientdata(fake_client, NULL);
- fake_client->addr = address | 1;
- fake_client->adapter = adapter;
- fake_client->driver = &max6875_driver;
- fake_client->flags = 0;
- strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
-
- if ((err = i2c_attach_client(real_client)) != 0)
- goto exit_kfree2;
-
- if ((err = i2c_attach_client(fake_client)) != 0)
- goto exit_detach1;
-
- err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+ err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
if (err)
- goto exit_detach2;
+ goto exit_remove_fake;
return 0;
-exit_detach2:
- i2c_detach_client(fake_client);
-exit_detach1:
- i2c_detach_client(real_client);
-exit_kfree2:
- kfree(fake_client);
-exit_kfree1:
+exit_remove_fake:
+ i2c_unregister_device(data->fake_client);
+exit_kfree:
kfree(data);
return err;
}
-/* Will be called for both the real client and the fake client */
-static int max6875_detach_client(struct i2c_client *client)
+static int max6875_remove(struct i2c_client *client)
{
- int err;
struct max6875_data *data = i2c_get_clientdata(client);
- /* data is NULL for the fake client */
- if (data)
- sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
+ i2c_unregister_device(data->fake_client);
- err = i2c_detach_client(client);
- if (err)
- return err;
+ sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
+ kfree(data);
- if (data) /* real client */
- kfree(data);
- else /* fake client */
- kfree(client);
return 0;
}
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index f43c4e79b55e..5e46036cf664 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -14,8 +14,8 @@
#include <linux/i2c.h>
#include <linux/hwmon-sysfs.h>
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
+/* Addresses to scan: none, device is not autodetected */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(pca9539);
@@ -32,21 +32,27 @@ enum pca9539_cmd
PCA9539_DIRECTION_1 = 7,
};
-static int pca9539_attach_adapter(struct i2c_adapter *adapter);
-static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind);
-static int pca9539_detach_client(struct i2c_client *client);
+static int pca9539_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int pca9539_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int pca9539_remove(struct i2c_client *client);
+
+static struct i2c_device_id pca9539_id[] = {
+ { "pca9539", 0 },
+ { }
+};
/* This is the driver that will be inserted */
static struct i2c_driver pca9539_driver = {
.driver = {
.name = "pca9539",
},
- .attach_adapter = pca9539_attach_adapter,
- .detach_client = pca9539_detach_client,
-};
-
-struct pca9539_data {
- struct i2c_client client;
+ .probe = pca9539_probe,
+ .remove = pca9539_remove,
+ .id_table = pca9539_id,
+ .detect = pca9539_detect,
+ .address_data = &addr_data,
};
/* following are the sysfs callback functions */
@@ -105,75 +111,31 @@ static struct attribute_group pca9539_defattr_group = {
.attrs = pca9539_attributes,
};
-static int pca9539_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_probe(adapter, &addr_data, pca9539_detect);
-}
-
-/* This function is called by i2c_probe */
-static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int pca9539_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct pca9539_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto exit;
-
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet. */
- if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &pca9539_driver;
- new_client->flags = 0;
-
- if (kind < 0) {
- /* Detection: the pca9539 only has 8 registers (0-7).
- A read of 7 should succeed, but a read of 8 should fail. */
- if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
- (i2c_smbus_read_byte_data(new_client, 8) >= 0))
- goto exit_kfree;
- }
-
- strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE);
-
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_kfree;
+ return -ENODEV;
- /* Register sysfs hooks */
- err = sysfs_create_group(&new_client->dev.kobj,
- &pca9539_defattr_group);
- if (err)
- goto exit_detach;
+ strlcpy(info->type, "pca9539", I2C_NAME_SIZE);
return 0;
-
-exit_detach:
- i2c_detach_client(new_client);
-exit_kfree:
- kfree(data);
-exit:
- return err;
}
-static int pca9539_detach_client(struct i2c_client *client)
+static int pca9539_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- int err;
+ /* Register sysfs hooks */
+ return sysfs_create_group(&client->dev.kobj,
+ &pca9539_defattr_group);
+}
+static int pca9539_remove(struct i2c_client *client)
+{
sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index e5b31329b56e..efbe53c826a3 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -1,6 +1,4 @@
/*
- pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
Dan Eaton <dan.eaton@rocketlogix.com>
@@ -40,35 +38,40 @@
#include <linux/slab.h>
#include <linux/i2c.h>
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = {
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- I2C_CLIENT_END
-};
+/* Addresses to scan: none, device can't be detected */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
/* Each client has this additional data */
struct pcf8574_data {
- struct i2c_client client;
-
int write; /* Remember last written value */
};
-static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
-static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind);
-static int pcf8574_detach_client(struct i2c_client *client);
+static int pcf8574_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int pcf8574_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int pcf8574_remove(struct i2c_client *client);
static void pcf8574_init_client(struct i2c_client *client);
+static struct i2c_device_id pcf8574_id[] = {
+ { "pcf8574", 0 },
+ { "pcf8574a", 0 },
+ { }
+};
+
/* This is the driver that will be inserted */
static struct i2c_driver pcf8574_driver = {
.driver = {
.name = "pcf8574",
},
- .attach_adapter = pcf8574_attach_adapter,
- .detach_client = pcf8574_detach_client,
+ .probe = pcf8574_probe,
+ .remove = pcf8574_remove,
+ .id_table = pcf8574_id,
+ .detect = pcf8574_detect,
+ .address_data = &addr_data,
};
/* following are the sysfs callback functions */
@@ -121,42 +124,22 @@ static const struct attribute_group pcf8574_attr_group = {
* Real code
*/
-static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int pcf8574_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- return i2c_probe(adapter, &addr_data, pcf8574_detect);
-}
-
-/* This function is called by i2c_probe */
-static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
-{
- struct i2c_client *new_client;
- struct pcf8574_data *data;
- int err = 0;
- const char *client_name = "";
+ struct i2c_adapter *adapter = client->adapter;
+ const char *client_name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
- goto exit;
-
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet. */
- if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &pcf8574_driver;
- new_client->flags = 0;
+ return -ENODEV;
/* Now, we would do the remaining detection. But the PCF8574 is plainly
impossible to detect! Stupid chip. */
/* Determine the chip type */
if (kind <= 0) {
- if (address >= 0x38 && address <= 0x3f)
+ if (client->addr >= 0x38 && client->addr <= 0x3f)
kind = pcf8574a;
else
kind = pcf8574;
@@ -166,40 +149,43 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
client_name = "pcf8574a";
else
client_name = "pcf8574";
+ strlcpy(info->type, client_name, I2C_NAME_SIZE);
- /* Fill in the remaining client fields and put it into the global list */
- strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+ return 0;
+}
+
+static int pcf8574_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pcf8574_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/* Initialize the PCF8574 chip */
- pcf8574_init_client(new_client);
+ pcf8574_init_client(client);
/* 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)
- goto exit_detach;
+ goto exit_free;
return 0;
- exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
return err;
}
-static int pcf8574_detach_client(struct i2c_client *client)
+static int pcf8574_remove(struct i2c_client *client)
{
- int err;
-
sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c
index 3ea08ac0bfa3..4555415b8bda 100644
--- a/drivers/i2c/chips/pcf8575.c
+++ b/drivers/i2c/chips/pcf8575.c
@@ -32,11 +32,8 @@
#include <linux/slab.h> /* kzalloc() */
#include <linux/sysfs.h> /* sysfs_create_group() */
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = {
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- I2C_CLIENT_END
-};
+/* Addresses to scan: none, device can't be detected */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD;
@@ -44,13 +41,19 @@ I2C_CLIENT_INSMOD;
/* Each client has this additional data */
struct pcf8575_data {
- struct i2c_client client;
int write; /* last written value, or error code */
};
-static int pcf8575_attach_adapter(struct i2c_adapter *adapter);
-static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind);
-static int pcf8575_detach_client(struct i2c_client *client);
+static int pcf8575_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int pcf8575_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int pcf8575_remove(struct i2c_client *client);
+
+static struct i2c_device_id pcf8575_id[] = {
+ { "pcf8575", 0 },
+ { }
+};
/* This is the driver that will be inserted */
static struct i2c_driver pcf8575_driver = {
@@ -58,8 +61,11 @@ static struct i2c_driver pcf8575_driver = {
.owner = THIS_MODULE,
.name = "pcf8575",
},
- .attach_adapter = pcf8575_attach_adapter,
- .detach_client = pcf8575_detach_client,
+ .probe = pcf8575_probe,
+ .remove = pcf8575_remove,
+ .id_table = pcf8575_id,
+ .detect = pcf8575_detect,
+ .address_data = &addr_data,
};
/* following are the sysfs callback functions */
@@ -126,71 +132,55 @@ static const struct attribute_group pcf8575_attr_group = {
* Real code
*/
-static int pcf8575_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int pcf8575_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- return i2c_probe(adapter, &addr_data, pcf8575_detect);
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ /* This is the place to detect whether the chip at the specified
+ address really is a PCF8575 chip. However, there is no method known
+ to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
+
+ strlcpy(info->type, "pcf8575", I2C_NAME_SIZE);
+
+ return 0;
}
-/* This function is called by i2c_probe */
-static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8575_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
struct pcf8575_data *data;
- int err = 0;
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
- goto exit;
+ int err;
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet. */
data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
- client = &data->client;
i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &pcf8575_driver;
- strlcpy(client->name, "pcf8575", I2C_NAME_SIZE);
data->write = -EAGAIN;
- /* This is the place to detect whether the chip at the specified
- address really is a PCF8575 chip. However, there is no method known
- to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
-
- /* Tell the I2C layer a new client has arrived */
- err = i2c_attach_client(client);
- if (err)
- goto exit_free;
-
/* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group);
if (err)
- goto exit_detach;
+ goto exit_free;
return 0;
-exit_detach:
- i2c_detach_client(client);
exit_free:
kfree(data);
exit:
return err;
}
-static int pcf8575_detach_client(struct i2c_client *client)
+static int pcf8575_remove(struct i2c_client *client)
{
- int err;
-
sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group);
-
- err = i2c_detach_client(client);
- if (err)
- return err;
-
kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 66c7c3bb9429..df9eb164f893 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -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>
Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
the help of Jean Delvare <khali@linux-fr.org>
@@ -74,26 +72,37 @@ MODULE_PARM_DESC(input_mode,
#define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg))
struct pcf8591_data {
- struct i2c_client client;
struct mutex update_lock;
u8 control;
u8 aout;
};
-static int pcf8591_attach_adapter(struct i2c_adapter *adapter);
-static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind);
-static int pcf8591_detach_client(struct i2c_client *client);
+static int pcf8591_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int pcf8591_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int pcf8591_remove(struct i2c_client *client);
static void pcf8591_init_client(struct i2c_client *client);
static int pcf8591_read_channel(struct device *dev, int channel);
+static struct i2c_device_id pcf8591_id[] = {
+ { "pcf8591", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8591_id);
+
/* This is the driver that will be inserted */
static struct i2c_driver pcf8591_driver = {
+ .class = I2C_CLASS_HWMON, /* Nearest choice */
.driver = {
.name = "pcf8591",
},
- .attach_adapter = pcf8591_attach_adapter,
- .detach_client = pcf8591_detach_client,
+ .probe = pcf8591_probe,
+ .remove = pcf8591_remove,
+ .id_table = pcf8591_id,
+ .detect = pcf8591_detect,
+ .address_data = &addr_data,
};
/* following are the sysfs callback functions */
@@ -182,70 +191,57 @@ static const struct attribute_group pcf8591_attr_group_opt = {
/*
* Real code
*/
-static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_probe(adapter, &addr_data, pcf8591_detect);
-}
-/* This function is called by i2c_probe */
-static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int pcf8591_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct pcf8591_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE
| I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
- goto exit;
+ return -ENODEV;
+
+ /* Now, we would do the remaining detection. But the PCF8591 is plainly
+ impossible to detect! Stupid chip. */
+
+ strlcpy(info->type, "pcf8591", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int pcf8591_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pcf8591_data *data;
+ int err;
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet. */
if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &pcf8591_driver;
- new_client->flags = 0;
-
- /* Now, we would do the remaining detection. But the PCF8591 is plainly
- impossible to detect! Stupid chip. */
-
- /* Determine the chip type - only one kind supported! */
- if (kind <= 0)
- kind = pcf8591;
-
- /* Fill in the remaining client fields and put it into the global
- list */
- strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
+ i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_kfree;
-
/* Initialize the PCF8591 chip */
- pcf8591_init_client(new_client);
+ pcf8591_init_client(client);
/* 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)
- goto exit_detach;
+ goto exit_kfree;
/* Register input2 if not in "two differential inputs" mode */
if (input_mode != 3) {
- if ((err = device_create_file(&new_client->dev,
+ if ((err = device_create_file(&client->dev,
&dev_attr_in2_input)))
goto exit_sysfs_remove;
}
/* Register input3 only in "four single ended inputs" mode */
if (input_mode == 0) {
- if ((err = device_create_file(&new_client->dev,
+ if ((err = device_create_file(&client->dev,
&dev_attr_in3_input)))
goto exit_sysfs_remove;
}
@@ -253,26 +249,18 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
exit_sysfs_remove:
- sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
- sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
-exit_detach:
- i2c_detach_client(new_client);
+ sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
+ sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
exit_kfree:
kfree(data);
exit:
return err;
}
-static int pcf8591_detach_client(struct i2c_client *client)
+static int pcf8591_remove(struct i2c_client *client)
{
- int err;
-
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 97d826827956..f0216b74fc7b 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -29,13 +29,11 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/idr.h>
-#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/hardirq.h>
#include <linux/irqflags.h>
-#include <linux/semaphore.h>
#include <asm/uaccess.h>
#include "i2c-core.h"
@@ -44,7 +42,9 @@
static DEFINE_MUTEX(core_lock);
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_driver *driver = to_i2c_driver(dev->driver);
- const struct i2c_device_id *id;
int status;
- if (!driver->probe)
+ if (!driver->probe || !driver->id_table)
return -ENODEV;
client->driver = driver;
dev_dbg(dev, "probe\n");
- if (driver->id_table)
- id = i2c_match_id(driver->id_table, client);
- else
- id = NULL;
- status = driver->probe(client, id);
+ status = driver->probe(client, i2c_match_id(driver->id_table, client));
if (status)
client->driver = NULL;
return status;
@@ -416,6 +411,10 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data)
struct i2c_driver *driver = to_i2c_driver(d);
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) {
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
@@ -455,7 +454,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
if (adap->nr < __i2c_first_dynamic_bus_num)
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,
i2c_do_add_adapter);
@@ -561,8 +560,19 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
{
struct i2c_driver *driver = to_i2c_driver(d);
struct i2c_adapter *adapter = data;
+ struct i2c_client *client, *_n;
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)
return 0;
res = driver->detach_adapter(adapter);
@@ -582,8 +592,7 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
*/
int i2c_del_adapter(struct i2c_adapter *adap)
{
- struct list_head *item, *_n;
- struct i2c_client *client;
+ struct i2c_client *client, *_n;
int res = 0;
mutex_lock(&core_lock);
@@ -604,10 +613,9 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because
* 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;
- client = list_entry(item, struct i2c_client, list);
driver = client->driver;
/* new style, follow standard driver model */
@@ -646,12 +654,17 @@ EXPORT_SYMBOL(i2c_del_adapter);
/* ------------------------------------------------------------------------- */
-static int attach_device(struct device *dev, void *data)
+static int __attach_adapter(struct device *dev, void *data)
{
struct i2c_adapter *adapter = to_i2c_adapter(dev);
struct i2c_driver *driver = data;
- driver->attach_adapter(adapter);
+ i2c_detect(adapter, driver);
+
+ /* Legacy drivers scan i2c busses directly */
+ if (driver->attach_adapter)
+ driver->attach_adapter(adapter);
+
return 0;
}
@@ -694,50 +707,57 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
- /* legacy drivers scan i2c busses directly */
- if (driver->attach_adapter)
- class_for_each_device(&i2c_adapter_class, NULL,
- (void *)driver, attach_device);
+ INIT_LIST_HEAD(&driver->clients);
+ /* Walk the adapters that are already present */
+ class_for_each_device(&i2c_adapter_class, NULL, driver,
+ __attach_adapter);
mutex_unlock(&core_lock);
return 0;
}
EXPORT_SYMBOL(i2c_register_driver);
-static int detach_device(struct device *dev, void *data)
+static int __detach_adapter(struct device *dev, void *data)
{
struct i2c_adapter *adapter = to_i2c_adapter(dev);
struct i2c_driver *driver = data;
- struct list_head *item2;
- struct list_head *_n;
- struct i2c_client *client;
+ 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",
+ if (driver->detach_adapter(adapter))
+ dev_err(&adapter->dev,
+ "detach_adapter failed for driver [%s]\n",
driver->driver.name);
- }
} else {
- list_for_each_safe(item2, _n, &adapter->clients) {
- client = list_entry(item2, struct i2c_client, list);
+ 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_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);
- }
+ "failed for client [%s] at 0x%02x\n",
+ client->name, client->addr);
}
}
+
return 0;
}
@@ -750,15 +770,9 @@ void i2c_del_driver(struct i2c_driver *driver)
{
mutex_lock(&core_lock);
- /* new-style driver? */
- if (is_newstyle_driver(driver))
- goto unregister;
-
- /* old-style driver, do it by hand */
- class_for_each_device(&i2c_adapter_class, NULL, (void *)driver,
- detach_device);
+ class_for_each_device(&i2c_adapter_class, NULL, driver,
+ __detach_adapter);
- unregister:
driver_unregister(&driver->driver);
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
@@ -871,8 +885,9 @@ EXPORT_SYMBOL(i2c_detach_client);
*/
struct i2c_client *i2c_use_client(struct i2c_client *client)
{
- get_device(&client->dev);
- return client;
+ if (client && get_device(&client->dev))
+ return client;
+ return NULL;
}
EXPORT_SYMBOL(i2c_use_client);
@@ -884,7 +899,8 @@ EXPORT_SYMBOL(i2c_use_client);
*/
void i2c_release_client(struct i2c_client *client)
{
- put_device(&client->dev);
+ if (client)
+ put_device(&client->dev);
}
EXPORT_SYMBOL(i2c_release_client);
@@ -950,10 +966,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 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) {
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
@@ -979,11 +1024,19 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
- return -ENOSYS;
+ return -EOPNOTSUPP;
}
}
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 ret;
@@ -1003,6 +1056,14 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
}
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)
{
struct i2c_adapter *adap=client->adapter;
@@ -1111,7 +1172,7 @@ int i2c_probe(struct i2c_adapter *adapter,
dev_warn(&adapter->dev, "SMBus Quick command not supported, "
"can't probe for chips\n");
- return -1;
+ return -EOPNOTSUPP;
}
/* Probe entries are done second, and are not affected by ignore
@@ -1165,6 +1226,178 @@ int i2c_probe(struct i2c_adapter *adapter,
}
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, "Detection function returned "
+ "inconsistent data for 0x%x\n", 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 *
i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info,
@@ -1303,29 +1536,38 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
if (rpec != cpec) {
pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
rpec, cpec);
- return -1;
+ return -EBADMSG;
}
return 0;
}
-s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
-{
- return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- value,0,I2C_SMBUS_QUICK,NULL);
-}
-EXPORT_SYMBOL(i2c_smbus_write_quick);
-
+/**
+ * i2c_smbus_read_byte - SMBus "receive byte" protocol
+ * @client: Handle to slave device
+ *
+ * This executes the SMBus "receive byte" protocol, returning negative errno
+ * else the byte received from the device.
+ */
s32 i2c_smbus_read_byte(struct i2c_client *client)
{
union i2c_smbus_data data;
- if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
- return -1;
- else
- return data.byte;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE, &data);
+ return (status < 0) ? status : data.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)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -1333,17 +1575,35 @@ s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
}
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)
{
union i2c_smbus_data data;
- if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
- return -1;
- else
- return data.byte;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ return (status < 0) ? status : data.byte;
}
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)
{
union i2c_smbus_data data;
@@ -1354,17 +1614,35 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
}
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)
{
union i2c_smbus_data data;
- if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
- return -1;
- else
- return data.word;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_WORD_DATA, &data);
+ return (status < 0) ? status : data.word;
}
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)
{
union i2c_smbus_data data;
@@ -1376,15 +1654,14 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
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
- * @command: Command byte issued to let the slave know what data should
- * be returned
+ * @command: Byte interpreted by slave
* @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.
*
- * Returns the number of bytes read in the slave's response, else a
- * negative number to indicate some kind of error.
+ * This executes the SMBus "block read" protocol, returning negative errno
+ * else the number of data bytes in the slave's response.
*
* Note that using this function requires that the client's adapter support
* the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality. Not all adapter drivers
@@ -1395,17 +1672,29 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
u8 *values)
{
union i2c_smbus_data data;
+ int status;
- if (i2c_smbus_xfer(client->adapter, client->addr, client->flags,
- I2C_SMBUS_READ, command,
- I2C_SMBUS_BLOCK_DATA, &data))
- return -1;
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_BLOCK_DATA, &data);
+ if (status)
+ return status;
memcpy(values, &data.block[1], data.block[0]);
return data.block[0];
}
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,
u8 length, const u8 *values)
{
@@ -1426,14 +1715,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
u8 length, u8 *values)
{
union i2c_smbus_data data;
+ int status;
if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX;
data.block[0] = length;
- if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command,
- I2C_SMBUS_I2C_BLOCK_DATA,&data))
- return -1;
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_I2C_BLOCK_DATA, &data);
+ if (status < 0)
+ return status;
memcpy(values, &data.block[1], data.block[0]);
return data.block[0];
@@ -1474,6 +1765,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
};
int i;
u8 partial_pec = 0;
+ int status;
msgbuf0[0] = command;
switch(size) {
@@ -1523,10 +1815,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
} else {
msg[0].len = data->block[0] + 2;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
- dev_err(&adapter->dev, "smbus_access called with "
- "invalid block write size (%d)\n",
- data->block[0]);
- return -1;
+ dev_err(&adapter->dev,
+ "Invalid block write size %d\n",
+ data->block[0]);
+ return -EINVAL;
}
for (i = 1; i < msg[0].len; i++)
msgbuf0[i] = data->block[i-1];
@@ -1536,10 +1828,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
num = 2; /* Another special case */
read_write = I2C_SMBUS_READ;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
- dev_err(&adapter->dev, "%s called with invalid "
- "block proc call size (%d)\n", __func__,
+ dev_err(&adapter->dev,
+ "Invalid block write size %d\n",
data->block[0]);
- return -1;
+ return -EINVAL;
}
msg[0].len = data->block[0] + 2;
for (i = 1; i < msg[0].len; i++)
@@ -1554,19 +1846,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
} else {
msg[0].len = data->block[0] + 1;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
- dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
- "invalid block write size (%d)\n",
- data->block[0]);
- return -1;
+ dev_err(&adapter->dev,
+ "Invalid block write size %d\n",
+ data->block[0]);
+ return -EINVAL;
}
for (i = 1; i <= data->block[0]; i++)
msgbuf0[i] = data->block[i];
}
break;
default:
- dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n",
- size);
- return -1;
+ dev_err(&adapter->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
}
i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
@@ -1584,13 +1875,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
msg[num-1].len++;
}
- if (i2c_transfer(adapter, msg, num) < 0)
- return -1;
+ status = i2c_transfer(adapter, msg, num);
+ if (status < 0)
+ return status;
/* Check PEC if last message is a read */
if (i && (msg[num-1].flags & I2C_M_RD)) {
- if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
- return -1;
+ status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
+ if (status < 0)
+ return status;
}
if (read_write == I2C_SMBUS_READ)
@@ -1618,9 +1911,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
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,
- char read_write, u8 command, int size,
+ char read_write, u8 command, int protocol,
union i2c_smbus_data * data)
{
s32 res;
@@ -1630,11 +1935,11 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
if (adapter->algo->smbus_xfer) {
mutex_lock(&adapter->bus_lock);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
- command,size,data);
+ command, protocol, data);
mutex_unlock(&adapter->bus_lock);
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
- command,size,data);
+ command, protocol, data);
return res;
}
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 7cd3c32dd0fb..30ef44768818 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -366,8 +366,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
return res;
}
-static int i2cdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = (struct i2c_client *)file->private_data;
unsigned long funcs;
@@ -487,7 +486,7 @@ static const struct file_operations i2cdev_fops = {
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
- .ioctl = i2cdev_ioctl,
+ .unlocked_ioctl = i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c
index a0df63289b5f..0cf96eb8a60f 100644
--- a/drivers/video/fb_ddc.c
+++ b/drivers/video/fb_ddc.c
@@ -106,6 +106,7 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
algo_data->setsda(algo_data->data, 1);
algo_data->setscl(algo_data->data, 1);
+ adapter->class |= I2C_CLASS_DDC;
return edid;
}
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index ca95f09d8b43..fcf9fadbf572 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -100,7 +100,8 @@ static int intelfb_gpio_getsda(void *data)
static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
struct intelfb_i2c_chan *chan,
- const u32 reg, const char *name)
+ const u32 reg, const char *name,
+ int class)
{
int rc;
@@ -108,6 +109,7 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
chan->reg = reg;
snprintf(chan->adapter.name, sizeof(chan->adapter.name),
"intelfb %s", name);
+ chan->adapter.class = class;
chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_HW_B_INTELFB;
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 */
intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
- "CRTDDC_A");
+ "CRTDDC_A", I2C_CLASS_DDC);
i++;
/* 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:
dinfo->output[i].type = INTELFB_OUTPUT_DVO;
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,
- GPIOE, "DVOI2C_E");
+ GPIOE, "DVOI2C_E", 0);
i++;
break;
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 */
dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
- GPIOE, "SDVOCTRL_E");
+ GPIOE, "SDVOCTRL_E", 0);
/* TODO: initialize the SDVO */
/* I830SDVOInit(pScrn, i, DVOB); */
i++;
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 4baab7be58de..c14e3e2212b3 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -87,13 +87,7 @@ static int matroxfb_gpio_getscl(void* data) {
return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
}
-static struct i2c_adapter matrox_i2c_adapter_template =
-{
- .owner = THIS_MODULE,
- .id = I2C_HW_B_G400,
-};
-
-static struct i2c_algo_bit_data matrox_i2c_algo_template =
+static const struct i2c_algo_bit_data matrox_i2c_algo_template =
{
.setsda = matroxfb_gpio_setsda,
.setscl = matroxfb_gpio_setscl,
@@ -104,16 +98,19 @@ 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,
- unsigned int data, unsigned int clock, const char* name) {
+ unsigned int data, unsigned int clock, const char *name,
+ int class)
+{
int err;
b->minfo = minfo;
b->mask.data = data;
b->mask.clock = clock;
- b->adapter = matrox_i2c_adapter_template;
+ b->adapter.owner = THIS_MODULE;
snprintf(b->adapter.name, sizeof(b->adapter.name), name,
minfo->fbcon.node);
i2c_set_adapdata(&b->adapter, b);
+ b->adapter.class = class;
b->adapter.algo_data = &b->bac;
b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev;
b->bac = matrox_i2c_algo_template;
@@ -159,24 +156,42 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
switch (ACCESS_FBINFO(chip)) {
case MGA_2064:
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;
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;
}
if (err)
goto fail_ddc1;
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) {
printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
} else if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
/* 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)
printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
+ else {
+ struct i2c_board_info maven_info = {
+ I2C_BOARD_INFO("maven", 0x1b),
+ };
+ unsigned short const addr_list[2] = {
+ 0x1b, I2C_CLIENT_END
+ };
+
+ i2c_new_probed_device(&m2info->maven.adapter,
+ &maven_info, addr_list);
+ }
}
return m2info;
fail_ddc1:;
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 89da27bd5c49..6d31eb4b674e 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -19,8 +19,6 @@
#include <linux/matroxfb.h>
#include <asm/div64.h>
-#define MAVEN_I2CID (0x1B)
-
#define MGATVO_B 1
#define MGATVO_C 2
@@ -128,7 +126,7 @@ static int get_ctrl_id(__u32 v4l2_id) {
struct maven_data {
struct matrox_fb_info* primary_head;
- struct i2c_client client;
+ struct i2c_client *client;
int version;
};
@@ -974,7 +972,7 @@ static inline int maven_compute_timming(struct maven_data* md,
static int maven_program_timming(struct maven_data* md,
const struct mavenregs* m) {
- struct i2c_client* c = &md->client;
+ struct i2c_client *c = md->client;
if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
LR(0x80);
@@ -1011,7 +1009,7 @@ static int maven_program_timming(struct maven_data* md,
}
static inline int maven_resync(struct maven_data* md) {
- struct i2c_client* c = &md->client;
+ struct i2c_client *c = md->client;
maven_set_reg(c, 0x95, 0x20); /* start whole thing */
return 0;
}
@@ -1069,48 +1067,48 @@ static int maven_set_control (struct maven_data* md,
maven_compute_bwlevel(md, &blacklevel, &whitelevel);
blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
- maven_set_reg_pair(&md->client, 0x0e, blacklevel);
- maven_set_reg_pair(&md->client, 0x1e, whitelevel);
+ maven_set_reg_pair(md->client, 0x0e, blacklevel);
+ maven_set_reg_pair(md->client, 0x1e, whitelevel);
}
break;
case V4L2_CID_SATURATION:
{
- maven_set_reg(&md->client, 0x20, p->value);
- maven_set_reg(&md->client, 0x22, p->value);
+ maven_set_reg(md->client, 0x20, p->value);
+ maven_set_reg(md->client, 0x22, p->value);
}
break;
case V4L2_CID_HUE:
{
- maven_set_reg(&md->client, 0x25, p->value);
+ maven_set_reg(md->client, 0x25, p->value);
}
break;
case V4L2_CID_GAMMA:
{
const struct maven_gamma* g;
g = maven_compute_gamma(md);
- maven_set_reg(&md->client, 0x83, g->reg83);
- maven_set_reg(&md->client, 0x84, g->reg84);
- maven_set_reg(&md->client, 0x85, g->reg85);
- maven_set_reg(&md->client, 0x86, g->reg86);
- maven_set_reg(&md->client, 0x87, g->reg87);
- maven_set_reg(&md->client, 0x88, g->reg88);
- maven_set_reg(&md->client, 0x89, g->reg89);
- maven_set_reg(&md->client, 0x8a, g->reg8a);
- maven_set_reg(&md->client, 0x8b, g->reg8b);
+ maven_set_reg(md->client, 0x83, g->reg83);
+ maven_set_reg(md->client, 0x84, g->reg84);
+ maven_set_reg(md->client, 0x85, g->reg85);
+ maven_set_reg(md->client, 0x86, g->reg86);
+ maven_set_reg(md->client, 0x87, g->reg87);
+ maven_set_reg(md->client, 0x88, g->reg88);
+ maven_set_reg(md->client, 0x89, g->reg89);
+ maven_set_reg(md->client, 0x8a, g->reg8a);
+ maven_set_reg(md->client, 0x8b, g->reg8b);
}
break;
case MATROXFB_CID_TESTOUT:
{
unsigned char val
- = maven_get_reg(&md->client,0x8d);
+ = maven_get_reg(md->client, 0x8d);
if (p->value) val |= 0x10;
else val &= ~0x10;
- maven_set_reg(&md->client, 0x8d, val);
+ maven_set_reg(md->client, 0x8d, val);
}
break;
case MATROXFB_CID_DEFLICKER:
{
- maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md));
+ maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
}
break;
}
@@ -1189,6 +1187,7 @@ static int maven_init_client(struct i2c_client* clnt) {
MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo);
md->primary_head = MINFO;
+ md->client = clnt;
down_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(outputs[1]).output = &maven_altout;
ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src;
@@ -1232,14 +1231,11 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
return 0;
}
-static const unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END };
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver maven_driver;
-
-static int maven_detect_client(struct i2c_adapter* adapter, int address, int kind) {
- int err = 0;
- struct i2c_client* new_client;
+static int maven_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int err = -ENODEV;
struct maven_data* data;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
@@ -1250,50 +1246,37 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin
err = -ENOMEM;
goto ERROR0;
}
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &maven_driver;
- new_client->flags = 0;
- strlcpy(new_client->name, "maven", I2C_NAME_SIZE);
- if ((err = i2c_attach_client(new_client)))
- goto ERROR3;
- err = maven_init_client(new_client);
+ i2c_set_clientdata(client, data);
+ err = maven_init_client(client);
if (err)
goto ERROR4;
return 0;
ERROR4:;
- i2c_detach_client(new_client);
-ERROR3:;
- kfree(new_client);
+ kfree(data);
ERROR0:;
return err;
}
-static int maven_attach_adapter(struct i2c_adapter* adapter) {
- if (adapter->id == I2C_HW_B_G400)
- return i2c_probe(adapter, &addr_data, &maven_detect_client);
- return 0;
-}
-
-static int maven_detach_client(struct i2c_client* client) {
- int err;
-
- if ((err = i2c_detach_client(client)))
- return err;
+static int maven_remove(struct i2c_client *client)
+{
maven_shutdown_client(client);
kfree(i2c_get_clientdata(client));
return 0;
}
+static struct i2c_device_id maven_id[] = {
+ { "maven", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, maven_id);
+
static struct i2c_driver maven_driver={
.driver = {
.name = "maven",
},
- .id = I2C_DRIVERID_MGATVO,
- .attach_adapter = maven_attach_adapter,
- .detach_client = maven_detach_client,
+ .probe = maven_probe,
+ .remove = maven_remove,
+ .id_table = maven_id,
};
static int __init matroxfb_maven_init(void)
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index 0fd5820d5c61..74c199dd41ec 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -94,21 +94,31 @@ static const u8 ds2482_chan_rd[8] =
#define DS2482_REG_STS_1WB 0x01
-static int ds2482_attach_adapter(struct i2c_adapter *adapter);
-static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind);
-static int ds2482_detach_client(struct i2c_client *client);
+static int ds2482_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int ds2482_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int ds2482_remove(struct i2c_client *client);
/**
* Driver data (common to all clients)
*/
+static struct i2c_device_id ds2482_id[] = {
+ { "ds2482", 0 },
+ { }
+};
+
static struct i2c_driver ds2482_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "ds2482",
},
- .attach_adapter = ds2482_attach_adapter,
- .detach_client = ds2482_detach_client,
+ .probe = ds2482_probe,
+ .remove = ds2482_remove,
+ .id_table = ds2482_id,
+ .detect = ds2482_detect,
+ .address_data = &addr_data,
};
/*
@@ -124,7 +134,7 @@ struct ds2482_w1_chan {
};
struct ds2482_data {
- struct i2c_client client;
+ struct i2c_client *client;
struct mutex access_lock;
/* 1-wire interface(s) */
@@ -147,7 +157,7 @@ struct ds2482_data {
static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr)
{
if (pdev->read_prt != read_ptr) {
- if (i2c_smbus_write_byte_data(&pdev->client,
+ if (i2c_smbus_write_byte_data(pdev->client,
DS2482_CMD_SET_READ_PTR,
read_ptr) < 0)
return -1;
@@ -167,7 +177,7 @@ static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr)
*/
static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd)
{
- if (i2c_smbus_write_byte(&pdev->client, cmd) < 0)
+ if (i2c_smbus_write_byte(pdev->client, cmd) < 0)
return -1;
pdev->read_prt = DS2482_PTR_CODE_STATUS;
@@ -187,7 +197,7 @@ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd)
static inline int ds2482_send_cmd_data(struct ds2482_data *pdev,
u8 cmd, u8 byte)
{
- if (i2c_smbus_write_byte_data(&pdev->client, cmd, byte) < 0)
+ if (i2c_smbus_write_byte_data(pdev->client, cmd, byte) < 0)
return -1;
/* all cmds leave in STATUS, except CONFIG */
@@ -216,7 +226,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev)
if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) {
do {
- temp = i2c_smbus_read_byte(&pdev->client);
+ temp = i2c_smbus_read_byte(pdev->client);
} while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) &&
(++retries < DS2482_WAIT_IDLE_TIMEOUT));
}
@@ -238,13 +248,13 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev)
*/
static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel)
{
- if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_CHANNEL_SELECT,
+ if (i2c_smbus_write_byte_data(pdev->client, DS2482_CMD_CHANNEL_SELECT,
ds2482_chan_wr[channel]) < 0)
return -1;
pdev->read_prt = DS2482_PTR_CODE_CHANNEL;
pdev->channel = -1;
- if (i2c_smbus_read_byte(&pdev->client) == ds2482_chan_rd[channel]) {
+ if (i2c_smbus_read_byte(pdev->client) == ds2482_chan_rd[channel]) {
pdev->channel = channel;
return 0;
}
@@ -368,7 +378,7 @@ static u8 ds2482_w1_read_byte(void *data)
ds2482_select_register(pdev, DS2482_PTR_CODE_DATA);
/* Read the data byte */
- result = i2c_smbus_read_byte(&pdev->client);
+ result = i2c_smbus_read_byte(pdev->client);
mutex_unlock(&pdev->access_lock);
@@ -415,47 +425,38 @@ static u8 ds2482_w1_reset_bus(void *data)
}
-/**
- * Called to see if the device exists on an i2c bus.
- */
-static int ds2482_attach_adapter(struct i2c_adapter *adapter)
+static int ds2482_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- return i2c_probe(adapter, &addr_data, ds2482_detect);
-}
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+ I2C_FUNC_SMBUS_BYTE))
+ return -ENODEV;
+ strlcpy(info->type, "ds2482", I2C_NAME_SIZE);
-/*
- * The following function does more than just detection. If detection
- * succeeds, it also registers the new chip.
- */
-static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
+ return 0;
+}
+
+static int ds2482_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ds2482_data *data;
- struct i2c_client *new_client;
- int err = 0;
+ int err = -ENODEV;
int temp1;
int idx;
- if (!i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
- I2C_FUNC_SMBUS_BYTE))
- goto exit;
-
if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->driver = &ds2482_driver;
- new_client->adapter = adapter;
+ data->client = client;
+ i2c_set_clientdata(client, data);
/* Reset the device (sets the read_ptr to status) */
if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) {
- dev_dbg(&adapter->dev, "DS2482 reset failed at 0x%02x.\n",
- address);
+ dev_warn(&client->dev, "DS2482 reset failed.\n");
goto exit_free;
}
@@ -463,10 +464,10 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
ndelay(525);
/* Read the status byte - only reset bit and line should be set */
- temp1 = i2c_smbus_read_byte(new_client);
+ temp1 = i2c_smbus_read_byte(client);
if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) {
- dev_dbg(&adapter->dev, "DS2482 (0x%02x) reset status "
- "0x%02X - not a DS2482\n", address, temp1);
+ dev_warn(&client->dev, "DS2482 reset status "
+ "0x%02X - not a DS2482\n", temp1);
goto exit_free;
}
@@ -478,16 +479,8 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
/* Set all config items to 0 (off) */
ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0);
- /* We can fill in the remaining client fields */
- snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00",
- data->w1_count);
-
mutex_init(&data->access_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
-
/* Register 1-wire interface(s) */
for (idx = 0; idx < data->w1_count; idx++) {
data->w1_ch[idx].pdev = data;
@@ -511,8 +504,6 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
exit_w1_remove:
- i2c_detach_client(new_client);
-
for (idx = 0; idx < data->w1_count; idx++) {
if (data->w1_ch[idx].pdev != NULL)
w1_remove_master_device(&data->w1_ch[idx].w1_bm);
@@ -523,10 +514,10 @@ exit:
return err;
}
-static int ds2482_detach_client(struct i2c_client *client)
+static int ds2482_remove(struct i2c_client *client)
{
struct ds2482_data *data = i2c_get_clientdata(client);
- int err, idx;
+ int idx;
/* Unregister the 1-wire bridge(s) */
for (idx = 0; idx < data->w1_count; idx++) {
@@ -534,13 +525,6 @@ static int ds2482_detach_client(struct i2c_client *client)
w1_remove_master_device(&data->w1_ch[idx].w1_bm);
}
- /* Detach the i2c device */
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Deregistration failed, client not detached.\n");
- return err;
- }
-
/* Free the memory */
kfree(data);
return 0;
diff --git a/include/linux/i2c-algo-pcf.h b/include/linux/i2c-algo-pcf.h
index 77afbb60fd11..0177d280f733 100644
--- a/include/linux/i2c-algo-pcf.h
+++ b/include/linux/i2c-algo-pcf.h
@@ -33,9 +33,11 @@ struct i2c_algo_pcf_data {
int (*getclock) (void *data);
void (*waitforpin) (void);
- /* local settings */
- int udelay;
- int timeout;
+ /* Multi-master lost arbitration back-off delay (msecs)
+ * This should be set by the bus adapter or knowledgable client
+ * if bus is multi-mastered, else zero
+ */
+ unsigned long lab_mdelay;
};
int i2c_pcf_add_bus(struct i2c_adapter *);
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 580acc93903e..ab08e2ac0c19 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -43,7 +43,6 @@
#define I2C_DRIVERID_TDA9850 20 /* audio mixer */
#define I2C_DRIVERID_TDA9855 21 /* audio mixer */
#define I2C_DRIVERID_SAA7110 22 /* video decoder */
-#define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */
#define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */
#define I2C_DRIVERID_PCF8583 25 /* real time clock */
#define I2C_DRIVERID_SAB3036 26 /* SAB3036 tuner */
@@ -104,14 +103,12 @@
#define I2C_HW_B_BT848 0x010005 /* BT848 video boards */
#define I2C_HW_B_VIA 0x010007 /* Via vt82c586b */
#define I2C_HW_B_HYDRA 0x010008 /* Apple Hydra Mac I/O */
-#define I2C_HW_B_G400 0x010009 /* Matrox G400 */
#define I2C_HW_B_I810 0x01000a /* Intel I810 */
#define I2C_HW_B_VOO 0x01000b /* 3dfx Voodoo 3 / Banshee */
#define I2C_HW_B_SCX200 0x01000e /* Nat'l Semi SCx200 I2C */
#define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */
#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_PCILYNX 0x01001a /* TI PCILynx I2C adapter */
#define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index fb9af6a0fe9c..7d62a9ebf2e7 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -43,6 +43,7 @@ struct i2c_adapter;
struct i2c_client;
struct i2c_driver;
union i2c_smbus_data;
+struct i2c_board_info;
/*
* The master routines are the ones normally used to transmit data to devices
@@ -69,9 +70,8 @@ extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
union i2c_smbus_data * data);
/* 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_write_byte(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@@ -93,15 +93,33 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
u8 command, u8 length,
const u8 *values);
-/*
- * A driver is capable of handling one or more physical devices present on
- * I2C adapters. This information is used to inform the driver of adapter
- * events.
+/**
+ * struct i2c_driver - represent an I2C device driver
+ * @class: What kind of i2c device we instantiate (for detect)
+ * @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.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 {
int id;
unsigned int class;
@@ -141,6 +159,11 @@ struct i2c_driver {
struct device_driver driver;
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)
@@ -156,6 +179,7 @@ struct i2c_driver {
* @dev: Driver model device node for the slave.
* @irq: indicates the IRQ generated by this device (if any)
* @list: list of active/busy clients (DEPRECATED)
+ * @detected: member of an i2c_driver.clients list
* @released: used to synchronize client releases & detaches and references
*
* An i2c_client identifies a single device (i.e. chip) connected to an
@@ -173,6 +197,7 @@ struct i2c_client {
struct device dev; /* the device structure */
int irq; /* irq issued by device (or -1) */
struct list_head list; /* DEPRECATED */
+ struct list_head detected;
struct completion released;
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -350,10 +375,11 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
#define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */
#define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
#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_DIGITAL (1<<5) /* most webcams */
#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 */
/* i2c_client_address_data is the struct for holding default client
@@ -537,7 +563,7 @@ union i2c_smbus_data {
/* 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_WRITE 0