Commit dc221eae authored by Linus Torvalds's avatar Linus Torvalds

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

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: (56 commits)
  i2c: Add detection capability to new-style drivers
  i2c: Call client_unregister for new-style devices too
  i2c: Clean up old chip drivers
  i2c-ibm_iic: Register child nodes
  i2c: New-style EEPROM driver using device IDs
  i2c: Export the i2c_bus_type symbol
  i2c-au1550: Fix PM support
  i2c-dev: Delete empty detach_client callback
  i2c: Drop stray references to lm_sensors
  i2c: Check for ACPI resource conflicts
  i2c-ocores: basic PM support
  i2c-sibyte: SWARM I2C board initialization
  i2c-i801: Fix handling of error conditions
  i2c-i801: Rename local variable temp to status
  i2c-i801: Properly report bus arbitration loss
  i2c-i801: Remove verbose debugging messages
  i2c-algo-pcf: Drop unused struct members
  i2c-algo-pcf: Multi-master lost-arbitration improvement
  i2c: Deprecate the legacy gpio drivers
  i2c-pxa: Initialize early
  ...
parents 98339cbd 4735c98f
...@@ -222,13 +222,6 @@ Who: Thomas Gleixner <tglx@linutronix.de> ...@@ -222,13 +222,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
--------------------------- ---------------------------
What: i2c-i810, i2c-prosavage and i2c-savage4
When: May 2008
Why: These drivers are superseded by i810fb, intelfb and savagefb.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
What (Why): What (Why):
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
(superseded by xt_TOS/xt_tos target & match) (superseded by xt_TOS/xt_tos target & match)
......
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.
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.
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.
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.
...@@ -42,8 +42,8 @@ Count (8 bits): A data byte containing the length of a block operation. ...@@ -42,8 +42,8 @@ Count (8 bits): A data byte containing the length of a block operation.
[..]: Data sent by I2C device, as opposed to data sent by the host adapter. [..]: Data sent by I2C device, as opposed to data sent by the host adapter.
SMBus Quick Command: i2c_smbus_write_quick() SMBus Quick Command
============================================= ===================
This sends a single bit to the device, at the place of the Rd/Wr bit. This sends a single bit to the device, at the place of the Rd/Wr bit.
......
...@@ -44,6 +44,10 @@ static struct i2c_driver foo_driver = { ...@@ -44,6 +44,10 @@ static struct i2c_driver foo_driver = {
.id_table = foo_ids, .id_table = foo_ids,
.probe = foo_probe, .probe = foo_probe,
.remove = foo_remove, .remove = foo_remove,
/* if device autodetection is needed: */
.class = I2C_CLASS_SOMETHING,
.detect = foo_detect,
.address_data = &addr_data,
/* else, driver uses "legacy" binding model: */ /* else, driver uses "legacy" binding model: */
.attach_adapter = foo_attach_adapter, .attach_adapter = foo_attach_adapter,
...@@ -217,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client ...@@ -217,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client
reference for later use. reference for later use.
Device Detection (Standard driver model)
----------------------------------------
Sometimes you do not know in advance which I2C devices are connected to
a given I2C bus. This is for example the case of hardware monitoring
devices on a PC's SMBus. In that case, you may want to let your driver
detect supported devices automatically. This is how the legacy model
was working, and is now available as an extension to the standard
driver model (so that we can finally get rid of the legacy model.)
You simply have to define a detect callback which will attempt to
identify supported devices (returning 0 for supported ones and -ENODEV
for unsupported ones), a list of addresses to probe, and a device type
(or class) so that only I2C buses which may have that type of device
connected (and not otherwise enumerated) will be probed. The i2c
core will then call you back as needed and will instantiate a device
for you for every successful detection.
Note that this mechanism is purely optional and not suitable for all
devices. You need some reliable way to identify the supported devices
(typically using device-specific, dedicated identification registers),
otherwise misdetections are likely to occur and things can get wrong
quickly.
Device Deletion (Standard driver model) Device Deletion (Standard driver model)
--------------------------------------- ---------------------------------------
...@@ -569,7 +598,6 @@ SMBus communication ...@@ -569,7 +598,6 @@ SMBus communication
in terms of it. Never use this function directly! in terms of it. Never use this function directly!
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte(struct i2c_client * client); extern s32 i2c_smbus_read_byte(struct i2c_client * client);
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value); extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
...@@ -578,30 +606,31 @@ SMBus communication ...@@ -578,30 +606,31 @@ SMBus communication
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_word_data(struct i2c_client * client, extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
u8 command, u16 value); u8 command, u16 value);
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
u8 command, u8 *values);
extern s32 i2c_smbus_write_block_data(struct i2c_client * client, extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
u8 command, u8 length, u8 command, u8 length,
u8 *values); u8 *values);
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
u8 command, u8 length, u8 *values); u8 command, u8 length, u8 *values);
These ones were removed in Linux 2.6.10 because they had no users, but could
be added back later if needed:
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
u8 command, u8 *values);
extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
u8 command, u8 length, u8 command, u8 length,
u8 *values); u8 *values);
These ones were removed from i2c-core because they had no users, but could
be added back later if needed:
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_process_call(struct i2c_client * client, extern s32 i2c_smbus_process_call(struct i2c_client * client,
u8 command, u16 value); u8 command, u16 value);
extern s32 i2c_smbus_block_process_call(struct i2c_client *client, extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
u8 command, u8 length, u8 command, u8 length,
u8 *values) u8 *values)
All these transactions return -1 on failure. The 'write' transactions All these transactions return a negative errno value on failure. The 'write'
return 0 on success; the 'read' transactions return the read value, except transactions return 0 on success; the 'read' transactions return the read
for read_block, which returns the number of values read. The block buffers value, except for block transactions, which return the number of values
need not be longer than 32 bytes. read. The block buffers need not be longer than 32 bytes.
You can read the file `smbus-protocol' for more information about the You can read the file `smbus-protocol' for more information about the
actual SMBus protocol. actual SMBus protocol.
......
...@@ -1686,6 +1686,13 @@ L: linuxppc-embedded@ozlabs.org ...@@ -1686,6 +1686,13 @@ L: linuxppc-embedded@ozlabs.org
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
FREESCALE I2C CPM DRIVER
P: Jochen Friedrich
M: jochen@scram.de
L: linuxppc-dev@ozlabs.org
L: i2c@lm-sensors.org
S: Maintained
FREESCALE SOC FS_ENET DRIVER FREESCALE SOC FS_ENET DRIVER
P: Pantelis Antoniou P: Pantelis Antoniou
M: pantelis.antoniou@gmail.com M: pantelis.antoniou@gmail.com
......
obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o
obj-$(CONFIG_I2C_BOARDINFO) += swarm-i2c.o
obj-$(CONFIG_KGDB) += dbg_io.o obj-$(CONFIG_KGDB) += dbg_io.o
/*
* 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);
...@@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap, ...@@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries) unsigned char addr, int retries)
{ {
struct i2c_algo_bit_data *adap = i2c_adap->algo_data; struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
int i, ret = -1; int i, ret = 0;
for (i = 0; i <= retries; i++) { for (i = 0; i <= retries; i++) {
ret = i2c_outb(i2c_adap, addr); ret = i2c_outb(i2c_adap, addr);
...@@ -508,7 +508,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) ...@@ -508,7 +508,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
addr ^= 1; addr ^= 1;
ret = try_address(i2c_adap, addr, retries); ret = try_address(i2c_adap, addr, retries);
if ((ret != 1) && !nak_ok) if ((ret != 1) && !nak_ok)
return -EREMOTEIO; return -ENXIO;
} }
return 0; return 0;
......
...@@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, ...@@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
} }
if (state != 0xf8) { if (state != 0xf8) {
dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state); dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
return -EIO; return -EAGAIN;
} }
DEB1("{{{ XFER %d messages\n", num); DEB1("{{{ XFER %d messages\n", num);
......
...@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap) ...@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
set_pcf(adap, 1, I2C_PCF_STOP); set_pcf(adap, 1, I2C_PCF_STOP);
} }
static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
{
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
*status));
/* Cleanup from LAB -- reset and enable ESO.
* This resets the PCF8584; since we've lost the bus, no
* further attempts should be made by callers to clean up
* (no i2c_stop() etc.)
*/
set_pcf(adap, 1, I2C_PCF_PIN);
set_pcf(adap, 1, I2C_PCF_ESO);
/* We pause for a time period sufficient for any running
* I2C transaction to complete -- the arbitration logic won't
* work properly until the next START is seen.
* It is assumed the bus driver or client has set a proper value.
*
* REVISIT: should probably use msleep instead of mdelay if we
* know we can sleep.
*/
if (adap->lab_mdelay)
mdelay(adap->lab_mdelay);
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
get_pcf(adap, 1)));
}
static int wait_for_bb(struct i2c_algo_pcf_data *adap) { static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
int timeout = DEF_TIMEOUT; int timeout = DEF_TIMEOUT;
...@@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { ...@@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
*status = get_pcf(adap, 1); *status = get_pcf(adap, 1);
} }
if (*status & I2C_PCF_LAB) { if (*status & I2C_PCF_LAB) {
DEB2(printk(KERN_INFO handle_lab(adap, status);
"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
*status));
/* Cleanup from LAB-- reset and enable ESO.
* This resets the PCF8584; since we've lost the bus, no
* further attempts should be made by callers to clean up
* (no i2c_stop() etc.)
*/
set_pcf(adap, 1, I2C_PCF_PIN);
set_pcf(adap, 1, I2C_PCF_ESO);
/* TODO: we should pause for a time period sufficient for any
* running I2C transaction to complete-- the arbitration
* logic won't work properly until the next START is seen.
*/
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
get_pcf(adap,1)));
return(-EINTR); return(-EINTR);
} }
#endif #endif
......
This diff is collapsed.
...@@ -2,57 +2,68 @@ ...@@ -2,57 +2,68 @@
# Makefile for the i2c bus drivers. # Makefile for the i2c bus drivers.
# #
# PC SMBus host controller drivers
obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o
obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o
obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_ISCH) += i2c-isch.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
# Mac SMBus host controller drivers
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
# Embebbed system I2C/SMBus host controller drivers
obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.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_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.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_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.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_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.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_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.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_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_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.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_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.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_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o # External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_STUB) += i2c-stub.o 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_TAOS_EVM) += i2c-taos-evm.o
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o # Graphics adapter I2C/DDC channel drivers
obj-$(CONFIG_I2C_VIA) += i2c-via.o
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
# Other I2C/SMBus bus drivers
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
......
/* /*
i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Philip Edelbrock <phil@netroedge.com>,
Mark D. Studebaker <mdsxyz123@yahoo.com>, Mark D. Studebaker <mdsxyz123@yahoo.com>,
...@@ -61,6 +59,7 @@ ...@@ -61,6 +59,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -159,6 +158,11 @@ static int ali1535_setup(struct pci_dev *dev) ...@@ -159,6 +158,11 @@ static int ali1535_setup(struct pci_dev *dev)
goto exit; goto exit;
} }
retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE,
ali1535_driver.name);
if (retval)
goto exit;
if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
ali1535_driver.name)) { ali1535_driver.name)) {
dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n", dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
...@@ -259,7 +263,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) ...@@ -259,7 +263,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
dev_err(&adap->dev, dev_err(&adap->dev,
"SMBus reset failed! (0x%02x) - controller or " "SMBus reset failed! (0x%02x) - controller or "
"device on bus is probably hung\n", temp); "device on bus is probably hung\n", temp);
return -1; return -EBUSY;
} }
} else { } else {
/* check and clear done bit */ /* check and clear done bit */
...@@ -281,12 +285,12 @@ static int ali1535_transaction(struct i2c_adapter *adap) ...@@ -281,12 +285,12 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n"); dev_err(&adap->dev, "SMBus Timeout!\n");
} }
if (temp & ALI1535_STS_FAIL) { if (temp & ALI1535_STS_FAIL) {
result = -1; result = -EIO;
dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
} }
...@@ -295,7 +299,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) ...@@ -295,7 +299,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
* do a printk. This means that bus collisions go unreported. * do a printk. This means that bus collisions go unreported.
*/ */
if (temp & ALI1535_STS_BUSERR) { if (temp & ALI1535_STS_BUSERR) {
result = -1; result = -ENXIO;
dev_dbg(&adap->dev, dev_dbg(&adap->dev,
"Error: no response or bus collision ADD=%02x\n", "Error: no response or bus collision ADD=%02x\n",
inb_p(SMBHSTADD)); inb_p(SMBHSTADD));
...@@ -303,13 +307,13 @@ static int ali1535_transaction(struct i2c_adapter *adap) ...@@ -303,13 +307,13 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* haven't ever seen this */ /* haven't ever seen this */
if (temp & ALI1535_STS_DEV) { if (temp & ALI1535_STS_DEV) {
result = -1; result = -EIO;
dev_err(&adap->dev, "Error: device error\n"); dev_err(&adap->dev, "Error: device error\n");
} }
/* check to see if the "command complete" indication is set */ /* check to see if the "command complete" indication is set */
if (!(temp & ALI1535_STS_DONE)) { if (!(temp & ALI1535_STS_DONE)) {
result = -1; result = -ETIMEDOUT;
dev_err(&adap->dev, "Error: command never completed\n"); dev_err(&adap->dev, "Error: command never completed\n");
} }
...@@ -332,7 +336,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) ...@@ -332,7 +336,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data) int size, union i2c_smbus_data *data)
...@@ -357,10 +361,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, ...@@ -357,10 +361,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
outb_p(0xFF, SMBHSTSTS); outb_p(0xFF, SMBHSTSTS);
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
result = -1;
goto EXIT;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD); SMBHSTADD);
...@@ -418,13 +418,15 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, ...@@ -418,13 +418,15 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
outb_p(data->block[i], SMBBLKDAT); outb_p(data->block[i], SMBBLKDAT);
} }
break; break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
result = -EOPNOTSUPP;
goto EXIT;
} }
if (ali1535_transaction(adap)) { result = ali1535_transaction(adap);
/* Error in transaction */ if (result)
result = -1;
goto EXIT; goto EXIT;
}
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) {
result = 0; result = 0;
...@@ -475,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = { ...@@ -475,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali1535_adapter = { static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI1535, .id = I2C_HW_SMBUS_ALI1535,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#define ALI1563_MAX_TIMEOUT 500 #define ALI1563_MAX_TIMEOUT 500
#define ALI1563_SMBBA 0x80 #define ALI1563_SMBBA 0x80
...@@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) ...@@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
{ {
u32 data; u32 data;
int timeout; int timeout;
int status = -EIO;
dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, " dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
...@@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) ...@@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
/* Issue 'kill' to host controller */ /* Issue 'kill' to host controller */
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
data = inb_p(SMB_HST_STS); data = inb_p(SMB_HST_STS);
status = -ETIMEDOUT;
} }
/* device error - no response, ignore the autodetection case */ /* device error - no response, ignore the autodetection case */
if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) { if (data & HST_STS_DEVERR) {
if (size != HST_CNTL2_QUICK)
dev_err(&a->dev, "Device error!\n"); dev_err(&a->dev, "Device error!\n");
status = -ENXIO;
} }
/* bus collision */ /* bus collision */
if (data & HST_STS_BUSERR) { if (data & HST_STS_BUSERR) {
dev_err(&a->dev, "Bus collision!\n"); dev_err(&a->dev, "Bus collision!\n");
...@@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) ...@@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
outb_p(0x0,SMB_HST_CNTL2); outb_p(0x0,SMB_HST_CNTL2);
} }
return -1; return status;
} }
static int ali1563_block_start(struct i2c_adapter * a) static int ali1563_block_start(struct i2c_adapter * a)
{ {
u32 data; u32 data;
int timeout; int timeout;
int status = -EIO;
dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, " dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
...@@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a) ...@@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD)) if (timeout && !(data & HST_STS_BAD))
return 0; return 0;
if (timeout == 0)
status = -ETIMEDOUT;
if (data & HST_STS_DEVERR)
status = -ENXIO;
dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n", dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
timeout ? "Timeout " : "", timeout ? "" : "Timeout ",
data & HST_STS_FAIL ? "Transaction Failed " : "", data & HST_STS_FAIL ? "Transaction Failed " : "",
data & HST_STS_BUSERR ? "No response or Bus Collision " : "", data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
data & HST_STS_DEVERR ? "Device Error " : "", data & HST_STS_DEVERR ? "Device Error " : "",
!(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
return -1; return status;
} }
static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
...@@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, ...@@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
/* Map the size to what the chip understands */ /* Map the size to what the chip understands */
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
error = -EINVAL;
break;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
size = HST_CNTL2_QUICK; size = HST_CNTL2_QUICK;
break; break;
...@@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, ...@@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
size = HST_CNTL2_BLOCK; size = HST_CNTL2_BLOCK;
break; break;
default:
dev_warn(&a->dev, "Unsupported transaction %d\n", size);
error = -EOPNOTSUPP;
goto Done;
} }
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
...@@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev) ...@@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
} }
} }
if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE,
ali1563_pci_driver.name))
goto Err;
if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE, if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
ali1563_pci_driver.name)) { ali1563_pci_driver.name)) {
dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n", dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
...@@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = { ...@@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = {
static struct i2c_adapter ali1563_adapter = { static struct i2c_adapter ali1563_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI1563, .id = I2C_HW_SMBUS_ALI1563,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ali1563_algorithm, .algo = &ali1563_algorithm,
}; };
......
/* /*
ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com> and Philip Edelbrock <phil@netroedge.com> and
Mark D. Studebaker <mdsxyz123@yahoo.com> Mark D. Studebaker <mdsxyz123@yahoo.com>
...@@ -68,6 +66,7 @@ ...@@ -68,6 +66,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* ALI15X3 SMBus address offsets */ /* ALI15X3 SMBus address offsets */
...@@ -166,6 +165,10 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev) ...@@ -166,6 +165,10 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
if(force_addr) if(force_addr)
ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
ali15x3_driver.name))
return -EBUSY;
if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
ali15x3_driver.name)) { ali15x3_driver.name)) {
dev_err(&ALI15X3_dev->dev, dev_err(&ALI15X3_dev->dev,
...@@ -282,7 +285,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) ...@@ -282,7 +285,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - " dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "
"controller or device on bus is probably hung\n", "controller or device on bus is probably hung\n",
temp); temp);
return -1; return -EBUSY;
} }
} else { } else {
/* check and clear done bit */ /* check and clear done bit */
...@@ -304,12 +307,12 @@ static int ali15x3_transaction(struct i2c_adapter *adap) ...@@ -304,12 +307,12 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n"); dev_err(&adap->dev, "SMBus Timeout!\n");
} }
if (temp & ALI15X3_STS_TERM) { if (temp & ALI15X3_STS_TERM) {
result = -1; result = -EIO;
dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
} }
...@@ -320,7 +323,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) ...@@ -320,7 +323,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
This means that bus collisions go unreported. This means that bus collisions go unreported.
*/ */
if (temp & ALI15X3_STS_COLL) { if (temp & ALI15X3_STS_COLL) {
result = -1; result = -ENXIO;
dev_dbg(&adap->dev, dev_dbg(&adap->dev,
"Error: no response or bus collision ADD=%02x\n", "Error: no response or bus collision ADD=%02x\n",
inb_p(SMBHSTADD)); inb_p(SMBHSTADD));
...@@ -328,7 +331,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) ...@@ -328,7 +331,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
/* haven't ever seen this */ /* haven't ever seen this */
if (temp & ALI15X3_STS_DEV) { if (temp & ALI15X3_STS_DEV) {
result = -1; result = -EIO;
dev_err(&adap->dev, "Error: device error\n"); dev_err(&adap->dev, "Error: device error\n");
} }
dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
...@@ -338,7 +341,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) ...@@ -338,7 +341,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
return result; return result;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data) int size, union i2c_smbus_data * data)
...@@ -362,9 +365,6 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -362,9 +365,6 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
} }
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD); SMBHSTADD);
...@@ -417,12 +417,16 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -417,12 +417,16 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
} }
size = ALI15X3_BLOCK_DATA; size = ALI15X3_BLOCK_DATA;
break; break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
} }
outb_p(size, SMBHSTCNT); /* output command */ outb_p(size, SMBHSTCNT); /* output command */
if (ali15x3_transaction(adap)) /* Error in transaction */ temp = ali15x3_transaction(adap);
return -1; if (temp)
return temp;
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
return 0; return 0;
...@@ -470,7 +474,7 @@ static const struct i2c_algorithm smbus_algorithm = { ...@@ -470,7 +474,7 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali15x3_adapter = { static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_ALI15X3, .id = I2C_HW_SMBUS_ALI15X3,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
......
...@@ -58,7 +58,7 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, ...@@ -58,7 +58,7 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
/* We exclude the multiplexed addresses */ /* We exclude the multiplexed addresses */
if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
|| addr == 0x18) || addr == 0x18)
return -1; return -ENXIO;
mutex_lock(&amd756_lock); mutex_lock(&amd756_lock);
...@@ -86,7 +86,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, ...@@ -86,7 +86,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
/* We exclude the non-multiplexed addresses */ /* We exclude the non-multiplexed addresses */
if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
return -1; return -ENXIO;
mutex_lock(&amd756_lock); mutex_lock(&amd756_lock);
......
/* /*
amd756.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
Shamelessly ripped from i2c-piix4.c: Shamelessly ripped from i2c-piix4.c:
...@@ -45,6 +42,7 @@ ...@@ -45,6 +42,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
/* AMD756 SMBus address offsets */ /* AMD756 SMBus address offsets */
...@@ -151,17 +149,17 @@ static int amd756_transaction(struct i2c_adapter *adap) ...@@ -151,17 +149,17 @@ static int amd756_transaction(struct i2c_adapter *adap)
} }
if (temp & GS_PRERR_STS) { if (temp & GS_PRERR_STS) {
result = -1; result = -ENXIO;
dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
} }
if (temp & GS_COL_STS) { if (temp & GS_COL_STS) {
result = -1; result = -EIO;
dev_warn(&adap->dev, "SMBus collision!\n"); dev_warn(&adap->dev, "SMBus collision!\n");
} }
if (temp & GS_TO_STS) { if (temp & GS_TO_STS) {
result = -1; result = -ETIMEDOUT;
dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); dev_dbg(&adap->dev, "SMBus protocol timeout!\n");
} }
...@@ -189,22 +187,18 @@ static int amd756_transaction(struct i2c_adapter *adap) ...@@ -189,22 +187,18 @@ static int amd756_transaction(struct i2c_adapter *adap)
outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
msleep(100); msleep(100);
outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
return -1; return -EIO;
} }
/* Return -1 on error. */ /* Return negative errno on error. */
static s32 amd756_access(struct i2c_adapter * adap, u16 addr, static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
{ {
int i, len; int i, len;
int status;
/** TODO: Should I supporte the 10-bit transfers? */
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL:
dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
/* TODO: Well... It is supported, I'm just not sure what to do here... */
return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMB_HOST_ADDRESS); SMB_HOST_ADDRESS);
...@@ -251,13 +245,17 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, ...@@ -251,13 +245,17 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
} }
size = AMD756_BLOCK_DATA; size = AMD756_BLOCK_DATA;
break; break;
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
} }
/* How about enabling interrupts... */ /* How about enabling interrupts... */
outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
if (amd756_transaction(adap)) /* Error in transaction */ status = amd756_transaction(adap);
return -1; if (status)
return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
return 0; return 0;
...@@ -301,7 +299,7 @@ static const struct i2c_algorithm smbus_algorithm = { ...@@ -301,7 +299,7 @@ static const struct i2c_algorithm smbus_algorithm = {
struct i2c_adapter amd756_smbus = { struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SMBUS_AMD756, .id = I2C_HW_SMBUS_AMD756,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
...@@ -368,6 +366,11 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -368,6 +366,11 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
amd756_ioport += SMB_ADDR_OFFSET; amd756_ioport += SMB_ADDR_OFFSET;
} }
error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
amd756_driver.name);
if (error)
return error;
if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
amd756_ioport); amd756_ioport);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -77,7 +78,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) ...@@ -77,7 +78,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
if (!timeout) { if (!timeout) {
dev_warn(&smbus->dev->dev, dev_warn(&smbus->dev->dev,
"Timeout while waiting for IBF to clear\n"); "Timeout while waiting for IBF to clear\n");
return -1; return -ETIMEDOUT;
} }
return 0; return 0;
...@@ -93,7 +94,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) ...@@ -93,7 +94,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
if (!timeout) { if (!timeout) {
dev_warn(&smbus->dev->dev, dev_warn(&smbus->dev->dev,
"Timeout while waiting for OBF to set\n"); "Timeout while waiting for OBF to set\n");
return -1; return -ETIMEDOUT;
} }
return 0; return 0;
...@@ -102,16 +103,21 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) ...@@ -102,16 +103,21 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
unsigned char *data) unsigned char *data)
{ {
if (amd_ec_wait_write(smbus)) int status;
return -1;
status = amd_ec_wait_write(smbus);
if (status)
return status;
outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD); outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
if (amd_ec_wait_write(smbus)) status = amd_ec_wait_write(smbus);
return -1; if (status)
return status;
outb(address, smbus->base + AMD_EC_DATA); outb(address, smbus->base + AMD_EC_DATA);
if (amd_ec_wait_read(smbus)) status = amd_ec_wait_read(smbus);
return -1; if (status)
return status;
*data = inb(smbus->base + AMD_EC_DATA); *data = inb(smbus->base + AMD_EC_DATA);
return 0; return 0;
...@@ -120,16 +126,21 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, ...@@ -120,16 +126,21 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
unsigned char data) unsigned char data)
{ {
if (amd_ec_wait_write(smbus)) int status;
return -1;
status = amd_ec_wait_write(smbus);
if (status)
return status;
outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD); outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
if (amd_ec_wait_write(smbus)) status = amd_ec_wait_write(smbus);
return -1; if (status)
return status;
outb(address, smbus->base + AMD_EC_DATA); outb(address, smbus->base + AMD_EC_DATA);
if (amd_ec_wait_write(smbus)) status = amd_ec_wait_write(smbus);
return -1; if (status)
return status;
outb(data, smbus->base + AMD_EC_DATA); outb(data, smbus->base + AMD_EC_DATA);
return 0; return 0;
...@@ -267,12 +278,17 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, ...@@ -267,12 +278,17 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
default: default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size); dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
} }
amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
/* FIXME this discards status from ec_read(); so temp[0] will
* hold stack garbage ... the rest of this routine will act
* nonsensically. Ignored ec_write() status might explain
* some such failures...
*/
amd_ec_read(smbus, AMD_SMB_STS, temp + 0); amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
if (~temp[0] & AMD_SMB_STS_DONE) { if (~temp[0] & AMD_SMB_STS_DONE) {
...@@ -286,7 +302,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, ...@@ -286,7 +302,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
} }
if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
return -1; return -EIO;
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
return 0; return 0;
...@@ -359,6 +375,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev, ...@@ -359,6 +375,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
smbus->base = pci_resource_start(dev, 0); smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0); smbus->size = pci_resource_len(dev, 0);
error = acpi_check_resource_conflict(&dev->resource[0]);
if (error)
goto out_kfree;
if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
error = -EBUSY; error = -EBUSY;
goto out_kfree; goto out_kfree;
...@@ -368,7 +388,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev, ...@@ -368,7 +388,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus2 AMD8111 adapter at %04x", smbus->base); "SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_HW_SMBUS_AMD8111; smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
......
...@@ -269,9 +269,13 @@ static int ...@@ -269,9 +269,13 @@ static int
au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{ {
struct i2c_au1550_data *adap = i2c_adap->algo_data; struct i2c_au1550_data *adap = i2c_adap->algo_data;
volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
struct i2c_msg *p; struct i2c_msg *p;
int i, err = 0; int i, err = 0;
sp->psc_ctrl = PSC_CTRL_ENABLE;
au_sync();
for (i = 0; !err && i < num; i++) { for (i = 0; !err && i < num; i++) {
p = &msgs[i]; p = &msgs[i];
err = do_address(adap, p->addr, p->flags & I2C_M_RD, err = do_address(adap, p->addr, p->flags & I2C_M_RD,
...@@ -288,6 +292,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) ...@@ -288,6 +292,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
*/ */
if (err == 0) if (err == 0)
err = num; err = num;
sp->psc_ctrl = PSC_CTRL_SUSPEND;
au_sync();
return err; return err;
} }
...@@ -302,6 +310,61 @@ static const struct i2c_algorithm au1550_algo = { ...@@ -302,6 +310,61 @@ static const struct i2c_algorithm au1550_algo = {
.functionality = au1550_func, .functionality = au1550_func,
}; };
static void i2c_au1550_setup(struct i2c_au1550_data *priv)
{
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
u32 stat;
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
sp->psc_smbcfg = 0;
au_sync();
sp->psc_ctrl = PSC_CTRL_ENABLE;
au_sync();
do {
stat = sp->psc_smbstat;
au_sync();
} while ((stat & PSC_SMBSTAT_SR) == 0);
sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
PSC_SMBCFG_DD_DISABLE);
/* Divide by 8 to get a 6.25 MHz clock. The later protocol
* timings are based on this clock.
*/
sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
au_sync();
/* Set the protocol timer values. See Table 71 in the
* Au1550 Data Book for standard timing values.
*/
sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
PSC_SMBTMR_SET_CH(15);
au_sync();
sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
do {
stat = sp->psc_smbstat;
au_sync();
} while ((stat & PSC_SMBSTAT_SR) == 0);
sp->psc_ctrl = PSC_CTRL_SUSPEND;
au_sync();
}
static void i2c_au1550_disable(struct i2c_au1550_data *priv)
{
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_smbcfg = 0;
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
}
/* /*
* registering functions to load algorithms at runtime * registering functions to load algorithms at runtime
* Prior to calling us, the 50MHz clock frequency and routing * Prior to calling us, the 50MHz clock frequency and routing
...@@ -311,9 +374,7 @@ static int __devinit ...@@ -311,9 +374,7 @@ static int __devinit
i2c_au1550_probe(struct platform_device *pdev) i2c_au1550_probe(struct platform_device *pdev)
{ {
struct i2c_au1550_data *priv; struct i2c_au1550_data *priv;
volatile psc_smb_t *sp;
struct resource *r; struct resource *r;
u32 stat;
int ret; int ret;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -348,43 +409,7 @@ i2c_au1550_probe(struct platform_device *pdev) ...@@ -348,43 +409,7 @@ i2c_au1550_probe(struct platform_device *pdev)
/* Now, set up the PSC for SMBus PIO mode. /* Now, set up the PSC for SMBus PIO mode.
*/ */
sp = (volatile psc_smb_t *)priv->psc_base; i2c_au1550_setup(priv);
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
sp->psc_smbcfg = 0;
au_sync();
sp->psc_ctrl = PSC_CTRL_ENABLE;
au_sync();
do {
stat = sp->psc_smbstat;
au_sync();
} while ((stat & PSC_SMBSTAT_SR) == 0);
sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
PSC_SMBCFG_DD_DISABLE);
/* Divide by 8 to get a 6.25 MHz clock. The later protocol
* timings are based on this clock.
*/
sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
au_sync();
/* Set the protocol timer values. See Table 71 in the
* Au1550 Data Book for standard timing values.
*/
sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
PSC_SMBTMR_SET_CH(15);
au_sync();
sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
do {
stat = sp->psc_smbstat;
au_sync();
} while ((stat & PSC_SMBSTAT_DR) == 0);
ret = i2c_add_numbered_adapter(&priv->adap); ret = i2c_add_numbered_adapter(&priv->adap);
if (ret == 0) { if (ret == 0) {
...@@ -392,10 +417,7 @@ i2c_au1550_probe(struct platform_device *pdev) ...@@ -392,10 +417,7 @@ i2c_au1550_probe(struct platform_device *pdev)
return 0; return 0;
} }
/* disable the PSC */ i2c_au1550_disable(priv);
sp->psc_smbcfg = 0;
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
release_resource(priv->ioarea); release_resource(priv->ioarea);
kfree(priv->ioarea); kfree(priv->ioarea);
...@@ -409,27 +431,24 @@ static int __devexit ...@@ -409,27 +431,24 @@ static int __devexit
i2c_au1550_remove(struct platform_device *pdev) i2c_au1550_remove(struct platform_device *pdev)
{ {
struct i2c_au1550_data *priv = platform_get_drvdata(pdev); struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
i2c_del_adapter(&priv->adap); i2c_del_adapter(&priv->adap);
sp->psc_smbcfg = 0; i2c_au1550_disable(priv);
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
release_resource(priv->ioarea); release_resource(priv->ioarea);
kfree(priv->ioarea); kfree(priv->ioarea);
kfree(priv); kfree(priv);
return 0; return 0;
} }
#ifdef CONFIG_PM
static int static int
i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state) i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
{ {
struct i2c_au1550_data *priv = platform_get_drvdata(pdev); struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_ctrl = PSC_CTRL_SUSPEND; i2c_au1550_disable(priv);
au_sync();
return 0; return 0;
} }
...@@ -437,14 +456,15 @@ static int ...@@ -437,14 +456,15 @@ static int
i2c_au1550_resume(struct platform_device *pdev) i2c_au1550_resume(struct platform_device *pdev)
{ {
struct i2c_au1550_data *priv = platform_get_drvdata(pdev); struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_ctrl = PSC_CTRL_ENABLE; i2c_au1550_setup(priv);
au_sync();
while (!(sp->psc_smbstat & PSC_SMBSTAT_SR))
au_sync();
return 0; return 0;
} }
#else
#define i2c_au1550_suspend NULL
#define i2c_au1550_resume NULL
#endif
static struct platform_driver au1xpsc_smbus_driver = { static struct platform_driver au1xpsc_smbus_driver = {
.driver = { .driver = {
......
This diff is collapsed.
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
#define DAVINCI_I2C_MDR_MST (1 << 10) #define DAVINCI_I2C_MDR_MST (1 << 10)
#define DAVINCI_I2C_MDR_TRX (1 << 9) #define DAVINCI_I2C_MDR_TRX (1 << 9)
#define DAVINCI_I2C_MDR_XA (1 << 8) #define DAVINCI_I2C_MDR_XA (1 << 8)
#define DAVINCI_I2C_MDR_RM (1 << 7)
#define DAVINCI_I2C_MDR_IRS (1 << 5) #define DAVINCI_I2C_MDR_IRS (1 << 5)
#define DAVINCI_I2C_IMR_AAS (1 << 6) #define DAVINCI_I2C_IMR_AAS (1 << 6)
...@@ -112,6 +113,7 @@ struct davinci_i2c_dev { ...@@ -112,6 +113,7 @@ struct davinci_i2c_dev {
u8 *buf; u8 *buf;
size_t buf_len; size_t buf_len;
int irq; int irq;
u8 terminate;
struct i2c_adapter adapter; struct i2c_adapter adapter;
}; };
...@@ -142,6 +144,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) ...@@ -142,6 +144,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
u16 psc; u16 psc;
u32 clk; u32 clk;
u32 d;
u32 clkh; u32 clkh;
u32 clkl; u32 clkl;
u32 input_clock = clk_get_rate(dev->clk); u32 input_clock = clk_get_rate(dev->clk);
...@@ -171,23 +174,29 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) ...@@ -171,23 +174,29 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
* if PSC > 1 , d = 5 * if PSC > 1 , d = 5
*/ */
psc = 26; /* To get 1MHz clock */ /* get minimum of 7 MHz clock, but max of 12 MHz */
psc = (input_clock / 7000000) - 1;
if ((input_clock / (psc + 1)) > 12000000)
psc++; /* better to run under spec than over */
d = (psc >= 2) ? 5 : 7 - psc;
clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - 10; clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1);
clkh = (50 * clk) / 100; clkh = clk >> 1;
clkl = clk - clkh; clkl = clk - clkh;
davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
dev_dbg(dev->dev, "CLK = %d\n", clk); dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
dev_dbg(dev->dev, "PSC = %d\n", dev_dbg(dev->dev, "PSC = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
dev_dbg(dev->dev, "CLKL = %d\n", dev_dbg(dev->dev, "CLKL = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
dev_dbg(dev->dev, "CLKH = %d\n", dev_dbg(dev->dev, "CLKH = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG));
dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n",
pdata->bus_freq, pdata->bus_delay);
/* Take the I2C module out of reset: */ /* Take the I2C module out of reset: */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
...@@ -233,7 +242,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -233,7 +242,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
u32 flag; u32 flag;
u32 stat;
u16 w; u16 w;
int r; int r;
...@@ -254,12 +262,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -254,12 +262,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len);
init_completion(&dev->cmd_complete); INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0; dev->cmd_err = 0;
/* Clear any pending interrupts by reading the IVR */
stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG);
/* Take I2C out of reset, configure it as master and set the /* Take I2C out of reset, configure it as master and set the
* start bit */ * start bit */
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
...@@ -280,20 +285,34 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -280,20 +285,34 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1); MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1);
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
dev->terminate = 0;
/* write the data into mode register */ /* write the data into mode register */
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
DAVINCI_I2C_TIMEOUT); DAVINCI_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
if (r == 0) { if (r == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
i2c_davinci_init(dev); i2c_davinci_init(dev);
dev->buf_len = 0;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
if (dev->buf_len) {
/* This should be 0 if all bytes were transferred
* or dev->cmd_err denotes an error.
* A signal may have aborted the transfer.
*/
if (r >= 0) {
dev_err(dev->dev, "abnormal termination buf_len=%i\n",
dev->buf_len);
r = -EREMOTEIO;
}
dev->terminate = 1;
wmb();
dev->buf_len = 0;
}
if (r < 0)
return r;
/* no error */ /* no error */
if (likely(!dev->cmd_err)) if (likely(!dev->cmd_err))
...@@ -338,12 +357,11 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -338,12 +357,11 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1))); ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1)));
dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
ret);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
return num; return num;
} }
...@@ -352,6 +370,27 @@ static u32 i2c_davinci_func(struct i2c_adapter *adap) ...@@ -352,6 +370,27 @@ static u32 i2c_davinci_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
} }
static void terminate_read(struct davinci_i2c_dev *dev)
{
u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_NACK;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
/* Throw away data */
davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG);
if (!dev->terminate)
dev_err(dev->dev, "RDR IRQ while no data requested\n");
}
static void terminate_write(struct davinci_i2c_dev *dev)
{
u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
if (!dev->terminate)
dev_err(dev->dev, "TDR IRQ while no data to send\n");
}
/* /*
* Interrupt service routine. This gets called whenever an I2C interrupt * Interrupt service routine. This gets called whenever an I2C interrupt
* occurs. * occurs.
...@@ -372,12 +411,15 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) ...@@ -372,12 +411,15 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
switch (stat) { switch (stat) {
case DAVINCI_I2C_IVR_AL: case DAVINCI_I2C_IVR_AL:
/* Arbitration lost, must retry */
dev->cmd_err |= DAVINCI_I2C_STR_AL; dev->cmd_err |= DAVINCI_I2C_STR_AL;
dev->buf_len = 0;
complete(&dev->cmd_complete); complete(&dev->cmd_complete);
break; break;
case DAVINCI_I2C_IVR_NACK: case DAVINCI_I2C_IVR_NACK:
dev->cmd_err |= DAVINCI_I2C_STR_NACK; dev->cmd_err |= DAVINCI_I2C_STR_NACK;
dev->buf_len = 0;
complete(&dev->cmd_complete); complete(&dev->cmd_complete);
break; break;
...@@ -399,9 +441,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) ...@@ -399,9 +441,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
davinci_i2c_write_reg(dev, davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_REG,
DAVINCI_I2C_IMR_RRDY); DAVINCI_I2C_IMR_RRDY);
} else } else {
dev_err(dev->dev, "RDR IRQ while no " /* signal can terminate transfer */
"data requested\n"); terminate_read(dev);
}
break; break;
case DAVINCI_I2C_IVR_XRDY: case DAVINCI_I2C_IVR_XRDY:
...@@ -418,9 +461,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) ...@@ -418,9 +461,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
davinci_i2c_write_reg(dev, davinci_i2c_write_reg(dev,
DAVINCI_I2C_IMR_REG, DAVINCI_I2C_IMR_REG,
w); w);
} else } else {
dev_err(dev->dev, "TDR IRQ while no data to " /* signal can terminate transfer */
"send\n"); terminate_write(dev);
}
break; break;
case DAVINCI_I2C_IVR_SCD: case DAVINCI_I2C_IVR_SCD:
...@@ -475,6 +519,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) ...@@ -475,6 +519,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
goto err_release_region; goto err_release_region;
} }
init_completion(&dev->cmd_complete);
dev->dev = get_device(&pdev->dev); dev->dev = get_device(&pdev->dev);
dev->irq = irq->start; dev->irq = irq->start;
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
......
...@@ -196,13 +196,11 @@ static struct i2c_algo_pcf_data pcf_isa_data = { ...@@ -196,13 +196,11 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
.getown = pcf_isa_getown, .getown = pcf_isa_getown,
.getclock = pcf_isa_getclock, .getclock = pcf_isa_getclock,
.waitforpin = pcf_isa_waitforpin, .waitforpin = pcf_isa_waitforpin,
.udelay = 10,
.timeout = 100,
}; };
static struct i2c_adapter pcf_isa_ops = { static struct i2c_adapter pcf_isa_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.id = I2C_HW_P_ELEK, .id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data, .algo_data = &pcf_isa_data,
.name = "i2c-elektor", .name = "i2c-elektor",
......
...@@ -140,7 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev) ...@@ -140,7 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data; adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev; adap->dev.parent = &pdev->dev;
/* /*
......
/* /*
i2c-hydra.c - Part of lm_sensors, Linux kernel modules
for hardware monitoring
i2c Support for the Apple `Hydra' Mac I/O i2c Support for the Apple `Hydra' Mac I/O
Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org> Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org>
......
This diff is collapsed.
/*
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);
...@@ -42,13 +42,8 @@ ...@@ -42,13 +42,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h> #include <linux/i2c-id.h>
#ifdef CONFIG_IBM_OCP
#include <asm/ocp.h>
#include <asm/ibm4xx.h>
#else
#include <linux/of_platform.h> #include <linux/of_platform.h>
#endif #include <linux/of_i2c.h>
#include "i2c-ibm_iic.h" #include "i2c-ibm_iic.h"
...@@ -665,180 +660,6 @@ static inline u8 iic_clckdiv(unsigned int opb) ...@@ -665,180 +660,6 @@ static inline u8 iic_clckdiv(unsigned int opb)
return (u8)((opb + 9) / 10 - 1); return (u8)((opb + 9) / 10 - 1);
} }
#ifdef CONFIG_IBM_OCP
/*
* Register single IIC interface
*/
static int __devinit iic_probe(struct ocp_device *ocp){
struct ibm_iic_private* dev;
struct i2c_adapter* adap;
struct ocp_func_iic_data* iic_data = ocp->def->additions;
int ret;
if (!iic_data)
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
ocp->def->index);
if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
ocp->def->index);
return -ENOMEM;
}
dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev);
if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
"ibm_iic")) {
ret = -EBUSY;
goto fail1;
}
if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
dev->idx);
ret = -ENXIO;
goto fail2;
}
init_waitqueue_head(&dev->wq);
dev->irq = iic_force_poll ? -1 : ocp->def->irq;
if (dev->irq >= 0){
/* Disable interrupts until we finish initialization,
assumes level-sensitive IRQ setup...
*/
iic_interrupt_mode(dev, 0);
if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
dev->idx, dev->irq);
/* Fallback to the polling mode */
dev->irq = -1;
}
}
if (dev->irq < 0)
printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
dev->idx);
/* Board specific settings */
dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
/* clckdiv is the same for *all* IIC interfaces,
* but I'd rather make a copy than introduce another global. --ebs
*/
dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
/* Initialize IIC interface */
iic_dev_init(dev);
/* Register it with i2c layer */
adap = &dev->adap;
adap->dev.parent = &ocp->dev;
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON;
adap->algo = &iic_algo;
adap->client_register = NULL;
adap->client_unregister = NULL;
adap->timeout = 1;
/*
* If "dev->idx" is negative we consider it as zero.
* The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters.
*/
adap->nr = dev->idx >= 0 ? dev->idx : 0;
if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
dev->idx);
goto fail;
}
printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
return 0;
fail:
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
fail2:
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
fail1:
ocp_set_drvdata(ocp, NULL);
kfree(dev);
return ret;
}
/*
* Cleanup initialized IIC interface
*/
static void __devexit iic_remove(struct ocp_device *ocp)
{
struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
BUG_ON(dev == NULL);
if (i2c_del_adapter(&dev->adap)){
printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
dev->idx);
/* That's *very* bad, just shutdown IRQ ... */
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
dev->irq = -1;
}
} else {
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
kfree(dev);
}
}
static struct ocp_device_id ibm_iic_ids[] __devinitdata =
{
{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
{ .vendor = OCP_VENDOR_INVALID }
};
MODULE_DEVICE_TABLE(ocp, ibm_iic_ids);
static struct ocp_driver ibm_iic_driver =
{
.name = "iic",
.id_table = ibm_iic_ids,
.probe = iic_probe,
.remove = __devexit_p(iic_remove),
#if defined(CONFIG_PM)
.suspend = NULL,
.resume = NULL,
#endif
};
static int __init iic_init(void)
{
printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
return ocp_register_driver(&ibm_iic_driver);
}
static void __exit iic_exit(void)
{
ocp_unregister_driver(&ibm_iic_driver);
}
#else /* !CONFIG_IBM_OCP */
static int __devinit iic_request_irq(struct of_device *ofdev, static int __devinit iic_request_irq(struct of_device *ofdev,
struct ibm_iic_private *dev) struct ibm_iic_private *dev)
{ {
...@@ -876,7 +697,7 @@ static int __devinit iic_probe(struct of_device *ofdev, ...@@ -876,7 +697,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
struct device_node *np = ofdev->node; struct device_node *np = ofdev->node;
struct ibm_iic_private *dev; struct ibm_iic_private *dev;
struct i2c_adapter *adap; struct i2c_adapter *adap;
const u32 *indexp, *freq; const u32 *freq;
int ret; int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
...@@ -887,14 +708,6 @@ static int __devinit iic_probe(struct of_device *ofdev, ...@@ -887,14 +708,6 @@ static int __devinit iic_probe(struct of_device *ofdev,
dev_set_drvdata(&ofdev->dev, dev); dev_set_drvdata(&ofdev->dev, dev);
indexp = of_get_property(np, "index", NULL);
if (!indexp) {
dev_err(&ofdev->dev, "no index specified\n");
ret = -EINVAL;
goto error_cleanup;
}
dev->idx = *indexp;
dev->vaddr = of_iomap(np, 0); dev->vaddr = of_iomap(np, 0);
if (dev->vaddr == NULL) { if (dev->vaddr == NULL) {
dev_err(&ofdev->dev, "failed to iomap device\n"); dev_err(&ofdev->dev, "failed to iomap device\n");
...@@ -934,17 +747,19 @@ static int __devinit iic_probe(struct of_device *ofdev, ...@@ -934,17 +747,19 @@ static int __devinit iic_probe(struct of_device *ofdev,
strlcpy(adap->name, "IBM IIC", sizeof(adap->name)); strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP; adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &iic_algo; adap->algo = &iic_algo;
adap->timeout = 1; adap->timeout = 1;
adap->nr = dev->idx;
ret = i2c_add_numbered_adapter(adap); ret = i2c_add_adapter(adap);
if (ret < 0) { if (ret < 0) {
dev_err(&ofdev->dev, "failed to register i2c adapter\n"); dev_err(&ofdev->dev, "failed to register i2c adapter\n");
goto error_cleanup; goto error_cleanup;
} }
/* Now register all the child nodes */
of_register_i2c_devices(adap, np);
dev_info(&ofdev->dev, "using %s mode\n", dev_info(&ofdev->dev, "using %s mode\n",
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
...@@ -987,11 +802,7 @@ static int __devexit iic_remove(struct of_device *ofdev) ...@@ -987,11 +802,7 @@ static int __devexit iic_remove(struct of_device *ofdev)
} }
static const struct of_device_id ibm_iic_match[] = { static const struct of_device_id ibm_iic_match[] = {
{ .compatible = "ibm,iic-405ex", }, { .compatible = "ibm,iic", },
{ .compatible = "ibm,iic-405gp", },
{ .compatible = "ibm,iic-440gp", },
{ .compatible = "ibm,iic-440gpx", },
{ .compatible = "ibm,iic-440grx", },
{} {}
}; };
...@@ -1011,7 +822,6 @@ static void __exit iic_exit(void) ...@@ -1011,7 +822,6 @@ static void __exit iic_exit(void)
{ {
of_unregister_platform_driver(&ibm_iic_driver); of_unregister_platform_driver(&ibm_iic_driver);
} }
#endif /* CONFIG_IBM_OCP */
module_init(iic_init); module_init(iic_init);
module_exit(iic_exit); module_exit(iic_exit);
...@@ -482,7 +482,7 @@ iop3xx_i2c_probe(struct platform_device *pdev) ...@@ -482,7 +482,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
new_adapter->id = I2C_HW_IOP3XX; new_adapter->id = I2C_HW_IOP3XX;
new_adapter->owner = THIS_MODULE; new_adapter->owner = THIS_MODULE;
new_adapter->class = I2C_CLASS_HWMON; new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
new_adapter->dev.parent = &pdev->dev; new_adapter->dev.parent = &pdev->dev;
new_adapter->nr = pdev->id; new_adapter->nr = pdev->id;
......
/*
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);
...@@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = { ...@@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = {
.name = "MPC adapter", .name = "MPC adapter",
.id = I2C_HW_MPC107, .id = I2C_HW_MPC107,
.algo = &mpc_algo, .algo = &mpc_algo,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.timeout = 1, .timeout = 1,
}; };
......
...@@ -530,7 +530,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) ...@@ -530,7 +530,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->adapter.id = I2C_HW_MV64XXX; drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE; drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON; drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
drv_data->adapter.timeout = pdata->timeout; drv_data->adapter.timeout = pdata->timeout;
drv_data->adapter.nr = pd->id; drv_data->adapter.nr = pd->id;
platform_set_drvdata(pd, drv_data); platform_set_drvdata(pd, drv_data);
......
/*
* 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);
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -124,6 +125,20 @@ static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = { ...@@ -124,6 +125,20 @@ static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
static struct pci_driver nforce2_driver; static struct pci_driver nforce2_driver;
/* For multiplexing support, we need a global reference to the 1st
SMBus channel */
#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE
struct i2c_adapter *nforce2_smbus;
EXPORT_SYMBOL_GPL(nforce2_smbus);
static void nforce2_set_reference(struct i2c_adapter *adap)
{
nforce2_smbus = adap;
}
#else
static inline void nforce2_set_reference(struct i2c_adapter *adap) { }
#endif
static void nforce2_abort(struct i2c_adapter *adap) static void nforce2_abort(struct i2c_adapter *adap)
{ {
struct nforce2_smbus *smbus = adap->algo_data; struct nforce2_smbus *smbus = adap->algo_data;
...@@ -158,16 +173,16 @@ static int nforce2_check_status(struct i2c_adapter *adap) ...@@ -158,16 +173,16 @@ static int nforce2_check_status(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "SMBus Timeout!\n"); dev_dbg(&adap->dev, "SMBus Timeout!\n");
if (smbus->can_abort) if (smbus->can_abort)
nforce2_abort(adap); nforce2_abort(adap);
return -1; return -ETIMEDOUT;
} }
if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) { if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp); dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp);
return -1; return -EIO;
} }
return 0; return 0;
} }
/* Return -1 on error */ /* Return negative errno on error */
static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
...@@ -175,7 +190,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, ...@@ -175,7 +190,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
struct nforce2_smbus *smbus = adap->algo_data; struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec; unsigned char protocol, pec;
u8 len; u8 len;
int i; int i, status;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
NVIDIA_SMB_PRTCL_WRITE; NVIDIA_SMB_PRTCL_WRITE;
...@@ -219,7 +234,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, ...@@ -219,7 +234,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
"Transaction failed " "Transaction failed "
"(requested block size: %d)\n", "(requested block size: %d)\n",
len); len);
return -1; return -EINVAL;
} }
outb_p(len, NVIDIA_SMB_BCNT); outb_p(len, NVIDIA_SMB_BCNT);
for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
...@@ -231,14 +246,15 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, ...@@ -231,14 +246,15 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
default: default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size); dev_err(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -EOPNOTSUPP;
} }
outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR); outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
outb_p(protocol, NVIDIA_SMB_PRTCL); outb_p(protocol, NVIDIA_SMB_PRTCL);
if (nforce2_check_status(adap)) status = nforce2_check_status(adap);
return -1; if (status)
return status;
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
return 0; return 0;
...@@ -260,7 +276,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, ...@@ -260,7 +276,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
dev_err(&adap->dev, "Transaction failed " dev_err(&adap->dev, "Transaction failed "
"(received block size: 0x%02x)\n", "(received block size: 0x%02x)\n",
len); len);
return -1; return -EPROTO;
} }
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
...@@ -321,21 +337,26 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, ...@@ -321,21 +337,26 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
!= PCIBIOS_SUCCESSFUL) { != PCIBIOS_SUCCESSFUL) {
dev_err(&dev->dev, "Error reading PCI config for %s\n", dev_err(&dev->dev, "Error reading PCI config for %s\n",
name); name);
return -1; return -EIO;
} }
smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
smbus->size = 64; smbus->size = 64;
} }
error = acpi_check_region(smbus->base, smbus->size,
nforce2_driver.name);
if (error)
return -1;
if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
smbus->base, smbus->base+smbus->size-1, name); smbus->base, smbus->base+smbus->size-1, name);
return -1; return -EBUSY;
} }
smbus->adapter.owner = THIS_MODULE; smbus->adapter.owner = THIS_MODULE;
smbus->adapter.id = I2C_HW_SMBUS_NFORCE2; smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
smbus->adapter.dev.parent = &dev->dev; smbus->adapter.dev.parent = &dev->dev;
...@@ -346,7 +367,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, ...@@ -346,7 +367,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
if (error) { if (error) {
dev_err(&smbus->adapter.dev, "Failed to register adapter.\n"); dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
release_region(smbus->base, smbus->size); release_region(smbus->base, smbus->size);
return -1; return error;
} }
dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base); dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base);
return 0; return 0;
...@@ -398,6 +419,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ ...@@ -398,6 +419,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
return -ENODEV; return -ENODEV;
} }
nforce2_set_reference(&smbuses[0].adapter);
return 0; return 0;
} }
...@@ -406,6 +428,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev) ...@@ -406,6 +428,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
{ {
struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev); struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
nforce2_set_reference(NULL);
if (smbuses[0].base) { if (smbuses[0].base) {
i2c_del_adapter(&smbuses[0].adapter); i2c_del_adapter(&smbuses[0].adapter);
release_region(smbuses[0].base, smbuses[0].size); release_region(smbuses[0].base, smbuses[0].size);
......
This diff is collapsed.
...@@ -365,7 +365,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, ...@@ -365,7 +365,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.owner = THIS_MODULE; smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"PA Semi SMBus adapter at 0x%lx", smbus->base); "PA Semi SMBus adapter at 0x%lx", smbus->base);
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
smbus->adapter.nr = PCI_FUNC(dev->devfn); smbus->adapter.nr = PCI_FUNC(dev->devfn);
......
...@@ -163,7 +163,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) ...@@ -163,7 +163,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
i2c->reg_base = ioremap(res->start, res_len(res)); i2c->reg_base = ioremap(res->start, res_len(res));
if (!i2c->reg_base) { if (!i2c->reg_base) {
ret = -EIO; ret = -ENOMEM;
goto e_remap; goto e_remap;
} }
i2c->io_base = res->start; i2c->io_base = res->start;
......
This diff is collapsed.
...@@ -622,7 +622,7 @@ static struct i2c_algorithm pmcmsptwi_algo = { ...@@ -622,7 +622,7 @@ static struct i2c_algorithm pmcmsptwi_algo = {
static struct i2c_adapter pmcmsptwi_adapter = { static struct i2c_adapter pmcmsptwi_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &pmcmsptwi_algo, .algo = &pmcmsptwi_algo,
.name = DRV_NAME, .name = DRV_NAME,
}; };
......
This diff is collapsed.
...@@ -1104,5 +1104,5 @@ static void __exit i2c_adap_pxa_exit(void) ...@@ -1104,5 +1104,5 @@ static void __exit i2c_adap_pxa_exit(void)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pxa2xx-i2c"); MODULE_ALIAS("platform:pxa2xx-i2c");
module_init(i2c_adap_pxa_init); subsys_initcall(i2c_adap_pxa_init);
module_exit(i2c_adap_pxa_exit); module_exit(i2c_adap_pxa_exit);
...@@ -590,7 +590,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = { ...@@ -590,7 +590,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm, .algo = &s3c24xx_i2c_algorithm,
.retries = 2, .retries = 2,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
}, },
}; };
......
This diff is collapsed.
...@@ -143,7 +143,7 @@ static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) ...@@ -143,7 +143,7 @@ static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
return i2c_add_adapter(i2c_adap); return i2c_add_numbered_adapter(i2c_adap);
} }
...@@ -156,17 +156,19 @@ static struct i2c_adapter sibyte_board_adapter[2] = { ...@@ -156,17 +156,19 @@ static struct i2c_adapter sibyte_board_adapter[2] = {
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SIBYTE, .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL, .algo = NULL,
.algo_data = &sibyte_board_data[0], .algo_data = &sibyte_board_data[0],
.nr = 0,
.name = "SiByte SMBus 0", .name = "SiByte SMBus 0",
}, },
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_SIBYTE, .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL, .algo = NULL,
.algo_data = &sibyte_board_data[1], .algo_data = &sibyte_board_data[1],
.nr = 1,
.name = "SiByte SMBus 1", .name = "SiByte SMBus 1",
}, },
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment