Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 358800
b: refs/heads/master
c: 974d6a3
h: refs/heads/master
v: v3
  • Loading branch information
Amaury Decrême authored and Wolfram Sang committed Feb 11, 2013
1 parent 1ac1909 commit e3391dd
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b08369a174a183e88baa98ab5e3566a617a3a7f8
refs/heads/master: 974d6a3797001c88e59ccb78567c6d71ac526c43
9 changes: 9 additions & 0 deletions trunk/Documentation/i2c/busses/i2c-sis630
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ Supported adapters:
* Silicon Integrated Systems Corp (SiS)
630 chipset (Datasheet: available at http://www.sfr-fresh.com/linux)
730 chipset
964 chipset
* Possible other SiS chipsets ?

Author: Alexander Malysh <amalysh@web.de>
Amaury Decrême <amaury.decreme@gmail.com> - SiS964 support

Module Parameters
-----------------
Expand All @@ -18,6 +20,7 @@ Module Parameters
* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
what your BIOS use). DANGEROUS! This should be a bit
faster, but freeze some systems (i.e. my Laptop).
SIS630/730 chip only.


Description
Expand All @@ -36,6 +39,12 @@ or like this:
00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02)
00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513

or like this:

00:00.0 Host bridge: Silicon Integrated Systems [SiS] 760/M760 Host (rev 02)
00:02.0 ISA bridge: Silicon Integrated Systems [SiS] SiS964 [MuTIOL Media IO]
LPC Controller (rev 36)

in your 'lspci' output , then this driver is for your chipset.

Thank You
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/i2c/busses/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ config I2C_SIS5595
will be called i2c-sis5595.

config I2C_SIS630
tristate "SiS 630/730"
tristate "SiS 630/730/964"
depends on PCI
help
If you say yes to this option, support will be included for the
SiS630 and SiS730 SMBus (a subset of I2C) interface.
SiS630, SiS730 and SiS964 SMBus (a subset of I2C) interface.

This driver can also be built as a module. If so, the module
will be called i2c-sis630.
Expand Down
88 changes: 58 additions & 30 deletions trunk/drivers/i2c/busses/i2c-sis630.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@
Supports:
SIS 630
SIS 730
SIS 964
Notable differences between chips:
+------------------------+--------------------+-------------------+
| | SIS630/730 | SIS964 |
+------------------------+--------------------+-------------------+
| Clock | 14kHz/56kHz | 55.56kHz/27.78kHz |
| SMBus registers offset | 0x80 | 0xE0 |
| SMB_CNT | Bit 1 = Slave Busy | Bit 1 = Bus probe |
| (not used yet) | Bit 3 is reserved | Bit 3 = Last byte |
| SMB_PCOUNT | Offset + 0x06 | Offset + 0x14 |
| SMB_COUNT | 4:0 bits | 5:0 bits |
+------------------------+--------------------+-------------------+
(Other differences don't affect the functions provided by the driver)
Note: we assume there can only be one device, with one SMBus interface.
*/
Expand All @@ -55,22 +69,21 @@
#include <linux/acpi.h>
#include <linux/io.h>

/* SIS630 SMBus registers */
#define SMB_STS 0x80 /* status */
#define SMB_EN 0x81 /* status enable */
#define SMB_CNT 0x82
#define SMBHOST_CNT 0x83
#define SMB_ADDR 0x84
#define SMB_CMD 0x85
#define SMB_PCOUNT 0x86 /* processed count */
#define SMB_COUNT 0x87
#define SMB_BYTE 0x88 /* ~0x8F data byte field */
#define SMBDEV_ADDR 0x90
#define SMB_DB0 0x91
#define SMB_DB1 0x92
#define SMB_SAA 0x93

/* register count for request_region */
/* SIS964 id is defined here as we are the only file using it */
#define PCI_DEVICE_ID_SI_964 0x0964

/* SIS630/730/964 SMBus registers */
#define SMB_STS 0x00 /* status */
#define SMB_CNT 0x02 /* control */
#define SMBHOST_CNT 0x03 /* host control */
#define SMB_ADDR 0x04 /* address */
#define SMB_CMD 0x05 /* command */
#define SMB_COUNT 0x07 /* byte count */
#define SMB_BYTE 0x08 /* ~0x8F data byte field */

/* register count for request_region
* As we don't use SMB_PCOUNT, 20 is ok for SiS630 and SiS964
*/
#define SIS630_SMB_IOREGION 20

/* PCI address constants */
Expand All @@ -96,28 +109,30 @@ static struct pci_driver sis630_driver;
static bool high_clock;
static bool force;
module_param(high_clock, bool, 0);
MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
MODULE_PARM_DESC(high_clock,
"Set Host Master Clock to 56KHz (default 14KHz) (SIS630/730 only).");
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");

/* acpi base address */
static unsigned short acpi_base;
/* SMBus base adress */
static unsigned short smbus_base;

/* supported chips */
static int supported[] = {
PCI_DEVICE_ID_SI_630,
PCI_DEVICE_ID_SI_730,
PCI_DEVICE_ID_SI_760,
0 /* terminates the list */
};

static inline u8 sis630_read(u8 reg)
{
return inb(acpi_base + reg);
return inb(smbus_base + reg);
}

static inline void sis630_write(u8 reg, u8 data)
{
outb(data, acpi_base + reg);
outb(data, smbus_base + reg);
}

static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock)
Expand Down Expand Up @@ -394,6 +409,8 @@ static int sis630_setup(struct pci_dev *sis630_dev)
unsigned char b;
struct pci_dev *dummy = NULL;
int retval, i;
/* acpi base address */
unsigned short acpi_base;

/* check for supported SiS devices */
for (i=0; supported[i] > 0 ; i++) {
Expand Down Expand Up @@ -438,16 +455,25 @@ static int sis630_setup(struct pci_dev *sis630_dev)

dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);

retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
if (supported[i] == PCI_DEVICE_ID_SI_760)
smbus_base = acpi_base + 0xE0;
else
smbus_base = acpi_base + 0x80;

dev_dbg(&sis630_dev->dev, "SMBus base at 0x%04hx\n", smbus_base);

retval = acpi_check_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name);
if (retval)
goto exit;

/* Everything is happy, let's grab the memory and set things up. */
if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name)) {
dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
dev_err(&sis630_dev->dev,
"I/O Region 0x%04hx-0x%04hx for SMBus already in use.\n",
smbus_base + SMB_STS,
smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);
retval = -EBUSY;
goto exit;
}
Expand All @@ -456,7 +482,7 @@ static int sis630_setup(struct pci_dev *sis630_dev)

exit:
if (retval)
acpi_base = 0;
smbus_base = 0;
return retval;
}

Expand All @@ -470,11 +496,13 @@ static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
.retries = 3
};

static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_964) },
{ 0, }
};

Expand All @@ -491,17 +519,17 @@ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
sis630_adapter.dev.parent = &dev->dev;

snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
"SMBus SIS630 adapter at %04x", acpi_base + SMB_STS);
"SMBus SIS630 adapter at %04hx", smbus_base + SMB_STS);

return i2c_add_adapter(&sis630_adapter);
}

static void sis630_remove(struct pci_dev *dev)
{
if (acpi_base) {
if (smbus_base) {
i2c_del_adapter(&sis630_adapter);
release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
acpi_base = 0;
release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
smbus_base = 0;
}
}

Expand Down

0 comments on commit e3391dd

Please sign in to comment.