15bc12008SAlek Du /* 25bc12008SAlek Du i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus 35bc12008SAlek Du - Based on i2c-piix4.c 45bc12008SAlek Du Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and 55bc12008SAlek Du Philip Edelbrock <phil@netroedge.com> 65bc12008SAlek Du - Intel SCH support 75bc12008SAlek Du Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com> 85bc12008SAlek Du 95bc12008SAlek Du This program is free software; you can redistribute it and/or modify 105bc12008SAlek Du it under the terms of the GNU General Public License version 2 as 115bc12008SAlek Du published by the Free Software Foundation. 125bc12008SAlek Du 135bc12008SAlek Du This program is distributed in the hope that it will be useful, 145bc12008SAlek Du but WITHOUT ANY WARRANTY; without even the implied warranty of 155bc12008SAlek Du MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165bc12008SAlek Du GNU General Public License for more details. 175bc12008SAlek Du 185bc12008SAlek Du You should have received a copy of the GNU General Public License 195bc12008SAlek Du along with this program; if not, write to the Free Software 205bc12008SAlek Du Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 215bc12008SAlek Du */ 225bc12008SAlek Du 235bc12008SAlek Du /* 245bc12008SAlek Du Supports: 255bc12008SAlek Du Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L) 265bc12008SAlek Du Note: we assume there can only be one device, with one SMBus interface. 275bc12008SAlek Du */ 285bc12008SAlek Du 295bc12008SAlek Du #include <linux/module.h> 305bc12008SAlek Du #include <linux/pci.h> 315bc12008SAlek Du #include <linux/kernel.h> 325bc12008SAlek Du #include <linux/delay.h> 335bc12008SAlek Du #include <linux/stddef.h> 345bc12008SAlek Du #include <linux/ioport.h> 355bc12008SAlek Du #include <linux/i2c.h> 365bc12008SAlek Du #include <linux/init.h> 375bc12008SAlek Du #include <linux/io.h> 3854fb4a05SJean Delvare #include <linux/acpi.h> 395bc12008SAlek Du 405bc12008SAlek Du /* SCH SMBus address offsets */ 415bc12008SAlek Du #define SMBHSTCNT (0 + sch_smba) 425bc12008SAlek Du #define SMBHSTSTS (1 + sch_smba) 435bc12008SAlek Du #define SMBHSTADD (4 + sch_smba) /* TSA */ 445bc12008SAlek Du #define SMBHSTCMD (5 + sch_smba) 455bc12008SAlek Du #define SMBHSTDAT0 (6 + sch_smba) 465bc12008SAlek Du #define SMBHSTDAT1 (7 + sch_smba) 475bc12008SAlek Du #define SMBBLKDAT (0x20 + sch_smba) 485bc12008SAlek Du 495bc12008SAlek Du /* count for request_region */ 505bc12008SAlek Du #define SMBIOSIZE 64 515bc12008SAlek Du 525bc12008SAlek Du /* PCI Address Constants */ 535bc12008SAlek Du #define SMBBA_SCH 0x40 545bc12008SAlek Du 555bc12008SAlek Du /* Other settings */ 565bc12008SAlek Du #define MAX_TIMEOUT 500 575bc12008SAlek Du 585bc12008SAlek Du /* I2C constants */ 595bc12008SAlek Du #define SCH_QUICK 0x00 605bc12008SAlek Du #define SCH_BYTE 0x01 615bc12008SAlek Du #define SCH_BYTE_DATA 0x02 625bc12008SAlek Du #define SCH_WORD_DATA 0x03 635bc12008SAlek Du #define SCH_BLOCK_DATA 0x05 645bc12008SAlek Du 655bc12008SAlek Du static unsigned short sch_smba; 665bc12008SAlek Du static struct pci_driver sch_driver; 675bc12008SAlek Du static struct i2c_adapter sch_adapter; 685bc12008SAlek Du 695bc12008SAlek Du /* 705bc12008SAlek Du * Start the i2c transaction -- the i2c_access will prepare the transaction 715bc12008SAlek Du * and this function will execute it. 725bc12008SAlek Du * return 0 for success and others for failure. 735bc12008SAlek Du */ 745bc12008SAlek Du static int sch_transaction(void) 755bc12008SAlek Du { 765bc12008SAlek Du int temp; 775bc12008SAlek Du int result = 0; 785bc12008SAlek Du int timeout = 0; 795bc12008SAlek Du 805bc12008SAlek Du dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " 815bc12008SAlek Du "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), 825bc12008SAlek Du inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0), 835bc12008SAlek Du inb(SMBHSTDAT1)); 845bc12008SAlek Du 855bc12008SAlek Du /* Make sure the SMBus host is ready to start transmitting */ 865bc12008SAlek Du temp = inb(SMBHSTSTS) & 0x0f; 875bc12008SAlek Du if (temp) { 885bc12008SAlek Du /* Can not be busy since we checked it in sch_access */ 895bc12008SAlek Du if (temp & 0x01) { 905bc12008SAlek Du dev_dbg(&sch_adapter.dev, "Completion (%02x). " 915bc12008SAlek Du "Clear...\n", temp); 925bc12008SAlek Du } 935bc12008SAlek Du if (temp & 0x06) { 945bc12008SAlek Du dev_dbg(&sch_adapter.dev, "SMBus error (%02x). " 955bc12008SAlek Du "Resetting...\n", temp); 965bc12008SAlek Du } 975bc12008SAlek Du outb(temp, SMBHSTSTS); 985bc12008SAlek Du temp = inb(SMBHSTSTS) & 0x0f; 995bc12008SAlek Du if (temp) { 1005bc12008SAlek Du dev_err(&sch_adapter.dev, 1015bc12008SAlek Du "SMBus is not ready: (%02x)\n", temp); 1025bc12008SAlek Du return -EAGAIN; 1035bc12008SAlek Du } 1045bc12008SAlek Du } 1055bc12008SAlek Du 1065bc12008SAlek Du /* start the transaction by setting bit 4 */ 1075bc12008SAlek Du outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT); 1085bc12008SAlek Du 1095bc12008SAlek Du do { 1105bc12008SAlek Du msleep(1); 1115bc12008SAlek Du temp = inb(SMBHSTSTS) & 0x0f; 1125bc12008SAlek Du } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT)); 1135bc12008SAlek Du 1145bc12008SAlek Du /* If the SMBus is still busy, we give up */ 1154ccc28f7SRoel Kluin if (timeout > MAX_TIMEOUT) { 1165bc12008SAlek Du dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); 1175bc12008SAlek Du result = -ETIMEDOUT; 1185bc12008SAlek Du } 1195bc12008SAlek Du if (temp & 0x04) { 1205bc12008SAlek Du result = -EIO; 1215bc12008SAlek Du dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " 1225bc12008SAlek Du "locked until next hard reset. (sorry!)\n"); 1235bc12008SAlek Du /* Clock stops and slave is stuck in mid-transmission */ 1245bc12008SAlek Du } else if (temp & 0x02) { 1255bc12008SAlek Du result = -EIO; 1265bc12008SAlek Du dev_err(&sch_adapter.dev, "Error: no response!\n"); 1275bc12008SAlek Du } else if (temp & 0x01) { 1285bc12008SAlek Du dev_dbg(&sch_adapter.dev, "Post complete!\n"); 1295bc12008SAlek Du outb(temp, SMBHSTSTS); 1305bc12008SAlek Du temp = inb(SMBHSTSTS) & 0x07; 1315bc12008SAlek Du if (temp & 0x06) { 1325bc12008SAlek Du /* Completion clear failed */ 1335bc12008SAlek Du dev_dbg(&sch_adapter.dev, "Failed reset at end of " 1345bc12008SAlek Du "transaction (%02x), Bus error!\n", temp); 1355bc12008SAlek Du } 1365bc12008SAlek Du } else { 1375bc12008SAlek Du result = -ENXIO; 1385bc12008SAlek Du dev_dbg(&sch_adapter.dev, "No such address.\n"); 1395bc12008SAlek Du } 1405bc12008SAlek Du dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " 1415bc12008SAlek Du "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), 1425bc12008SAlek Du inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0), 1435bc12008SAlek Du inb(SMBHSTDAT1)); 1445bc12008SAlek Du return result; 1455bc12008SAlek Du } 1465bc12008SAlek Du 1475bc12008SAlek Du /* 1485bc12008SAlek Du * This is the main access entry for i2c-sch access 1495bc12008SAlek Du * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write 1505bc12008SAlek Du * (0 for read and 1 for write), size is i2c transaction type and data is the 1515bc12008SAlek Du * union of transaction for data to be transfered or data read from bus. 1525bc12008SAlek Du * return 0 for success and others for failure. 1535bc12008SAlek Du */ 1545bc12008SAlek Du static s32 sch_access(struct i2c_adapter *adap, u16 addr, 1555bc12008SAlek Du unsigned short flags, char read_write, 1565bc12008SAlek Du u8 command, int size, union i2c_smbus_data *data) 1575bc12008SAlek Du { 1585bc12008SAlek Du int i, len, temp, rc; 1595bc12008SAlek Du 1605bc12008SAlek Du /* Make sure the SMBus host is not busy */ 1615bc12008SAlek Du temp = inb(SMBHSTSTS) & 0x0f; 1625bc12008SAlek Du if (temp & 0x08) { 1635bc12008SAlek Du dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp); 1645bc12008SAlek Du return -EAGAIN; 1655bc12008SAlek Du } 1665bc12008SAlek Du dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size, 1675bc12008SAlek Du (read_write)?"READ":"WRITE"); 1685bc12008SAlek Du switch (size) { 1695bc12008SAlek Du case I2C_SMBUS_QUICK: 1705bc12008SAlek Du outb((addr << 1) | read_write, SMBHSTADD); 1715bc12008SAlek Du size = SCH_QUICK; 1725bc12008SAlek Du break; 1735bc12008SAlek Du case I2C_SMBUS_BYTE: 1745bc12008SAlek Du outb((addr << 1) | read_write, SMBHSTADD); 1755bc12008SAlek Du if (read_write == I2C_SMBUS_WRITE) 1765bc12008SAlek Du outb(command, SMBHSTCMD); 1775bc12008SAlek Du size = SCH_BYTE; 1785bc12008SAlek Du break; 1795bc12008SAlek Du case I2C_SMBUS_BYTE_DATA: 1805bc12008SAlek Du outb((addr << 1) | read_write, SMBHSTADD); 1815bc12008SAlek Du outb(command, SMBHSTCMD); 1825bc12008SAlek Du if (read_write == I2C_SMBUS_WRITE) 1835bc12008SAlek Du outb(data->byte, SMBHSTDAT0); 1845bc12008SAlek Du size = SCH_BYTE_DATA; 1855bc12008SAlek Du break; 1865bc12008SAlek Du case I2C_SMBUS_WORD_DATA: 1875bc12008SAlek Du outb((addr << 1) | read_write, SMBHSTADD); 1885bc12008SAlek Du outb(command, SMBHSTCMD); 1895bc12008SAlek Du if (read_write == I2C_SMBUS_WRITE) { 1905bc12008SAlek Du outb(data->word & 0xff, SMBHSTDAT0); 1915bc12008SAlek Du outb((data->word & 0xff00) >> 8, SMBHSTDAT1); 1925bc12008SAlek Du } 1935bc12008SAlek Du size = SCH_WORD_DATA; 1945bc12008SAlek Du break; 1955bc12008SAlek Du case I2C_SMBUS_BLOCK_DATA: 1965bc12008SAlek Du outb((addr << 1) | read_write, SMBHSTADD); 1975bc12008SAlek Du outb(command, SMBHSTCMD); 1985bc12008SAlek Du if (read_write == I2C_SMBUS_WRITE) { 1995bc12008SAlek Du len = data->block[0]; 2005bc12008SAlek Du if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) 2015bc12008SAlek Du return -EINVAL; 2025bc12008SAlek Du outb(len, SMBHSTDAT0); 2035bc12008SAlek Du for (i = 1; i <= len; i++) 2045bc12008SAlek Du outb(data->block[i], SMBBLKDAT+i-1); 2055bc12008SAlek Du } 2065bc12008SAlek Du size = SCH_BLOCK_DATA; 2075bc12008SAlek Du break; 2085bc12008SAlek Du default: 2095bc12008SAlek Du dev_warn(&adap->dev, "Unsupported transaction %d\n", size); 2105bc12008SAlek Du return -EOPNOTSUPP; 2115bc12008SAlek Du } 2125bc12008SAlek Du dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT); 2135bc12008SAlek Du outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT); 2145bc12008SAlek Du 2155bc12008SAlek Du rc = sch_transaction(); 2165bc12008SAlek Du if (rc) /* Error in transaction */ 2175bc12008SAlek Du return rc; 2185bc12008SAlek Du 2195bc12008SAlek Du if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK)) 2205bc12008SAlek Du return 0; 2215bc12008SAlek Du 2225bc12008SAlek Du switch (size) { 2235bc12008SAlek Du case SCH_BYTE: 2245bc12008SAlek Du case SCH_BYTE_DATA: 2255bc12008SAlek Du data->byte = inb(SMBHSTDAT0); 2265bc12008SAlek Du break; 2275bc12008SAlek Du case SCH_WORD_DATA: 2285bc12008SAlek Du data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8); 2295bc12008SAlek Du break; 2305bc12008SAlek Du case SCH_BLOCK_DATA: 2315bc12008SAlek Du data->block[0] = inb(SMBHSTDAT0); 2325bc12008SAlek Du if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) 2335bc12008SAlek Du return -EPROTO; 2345bc12008SAlek Du for (i = 1; i <= data->block[0]; i++) 2355bc12008SAlek Du data->block[i] = inb(SMBBLKDAT+i-1); 2365bc12008SAlek Du break; 2375bc12008SAlek Du } 2385bc12008SAlek Du return 0; 2395bc12008SAlek Du } 2405bc12008SAlek Du 2415bc12008SAlek Du static u32 sch_func(struct i2c_adapter *adapter) 2425bc12008SAlek Du { 2435bc12008SAlek Du return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 2445bc12008SAlek Du I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 2455bc12008SAlek Du I2C_FUNC_SMBUS_BLOCK_DATA; 2465bc12008SAlek Du } 2475bc12008SAlek Du 2485bc12008SAlek Du static const struct i2c_algorithm smbus_algorithm = { 2495bc12008SAlek Du .smbus_xfer = sch_access, 2505bc12008SAlek Du .functionality = sch_func, 2515bc12008SAlek Du }; 2525bc12008SAlek Du 2535bc12008SAlek Du static struct i2c_adapter sch_adapter = { 2545bc12008SAlek Du .owner = THIS_MODULE, 2553401b2ffSJean Delvare .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, 2565bc12008SAlek Du .algo = &smbus_algorithm, 2575bc12008SAlek Du }; 2585bc12008SAlek Du 2595bc12008SAlek Du static struct pci_device_id sch_ids[] = { 2605bc12008SAlek Du { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, 2615bc12008SAlek Du { 0, } 2625bc12008SAlek Du }; 2635bc12008SAlek Du 2645bc12008SAlek Du MODULE_DEVICE_TABLE(pci, sch_ids); 2655bc12008SAlek Du 2665bc12008SAlek Du static int __devinit sch_probe(struct pci_dev *dev, 2675bc12008SAlek Du const struct pci_device_id *id) 2685bc12008SAlek Du { 2695bc12008SAlek Du int retval; 2705bc12008SAlek Du unsigned int smba; 2715bc12008SAlek Du 2725bc12008SAlek Du pci_read_config_dword(dev, SMBBA_SCH, &smba); 2735bc12008SAlek Du if (!(smba & (1 << 31))) { 2745bc12008SAlek Du dev_err(&dev->dev, "SMBus I/O space disabled!\n"); 2755bc12008SAlek Du return -ENODEV; 2765bc12008SAlek Du } 2775bc12008SAlek Du 2785bc12008SAlek Du sch_smba = (unsigned short)smba; 2795bc12008SAlek Du if (sch_smba == 0) { 2805bc12008SAlek Du dev_err(&dev->dev, "SMBus base address uninitialized!\n"); 2815bc12008SAlek Du return -ENODEV; 2825bc12008SAlek Du } 28354fb4a05SJean Delvare if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name)) 28454fb4a05SJean Delvare return -EBUSY; 2855bc12008SAlek Du if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) { 2865bc12008SAlek Du dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", 2875bc12008SAlek Du sch_smba); 2885bc12008SAlek Du return -EBUSY; 2895bc12008SAlek Du } 2905bc12008SAlek Du dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba); 2915bc12008SAlek Du 2925bc12008SAlek Du /* set up the sysfs linkage to our parent device */ 2935bc12008SAlek Du sch_adapter.dev.parent = &dev->dev; 2945bc12008SAlek Du 2955bc12008SAlek Du snprintf(sch_adapter.name, sizeof(sch_adapter.name), 2965bc12008SAlek Du "SMBus SCH adapter at %04x", sch_smba); 2975bc12008SAlek Du 2985bc12008SAlek Du retval = i2c_add_adapter(&sch_adapter); 2995bc12008SAlek Du if (retval) { 3005bc12008SAlek Du dev_err(&dev->dev, "Couldn't register adapter!\n"); 3015bc12008SAlek Du release_region(sch_smba, SMBIOSIZE); 3025bc12008SAlek Du sch_smba = 0; 3035bc12008SAlek Du } 3045bc12008SAlek Du 3055bc12008SAlek Du return retval; 3065bc12008SAlek Du } 3075bc12008SAlek Du 3085bc12008SAlek Du static void __devexit sch_remove(struct pci_dev *dev) 3095bc12008SAlek Du { 3105bc12008SAlek Du if (sch_smba) { 3115bc12008SAlek Du i2c_del_adapter(&sch_adapter); 3125bc12008SAlek Du release_region(sch_smba, SMBIOSIZE); 3135bc12008SAlek Du sch_smba = 0; 3145bc12008SAlek Du } 3155bc12008SAlek Du } 3165bc12008SAlek Du 3175bc12008SAlek Du static struct pci_driver sch_driver = { 3185bc12008SAlek Du .name = "isch_smbus", 3195bc12008SAlek Du .id_table = sch_ids, 3205bc12008SAlek Du .probe = sch_probe, 3215bc12008SAlek Du .remove = __devexit_p(sch_remove), 3225bc12008SAlek Du }; 3235bc12008SAlek Du 3245bc12008SAlek Du static int __init i2c_sch_init(void) 3255bc12008SAlek Du { 3265bc12008SAlek Du return pci_register_driver(&sch_driver); 3275bc12008SAlek Du } 3285bc12008SAlek Du 3295bc12008SAlek Du static void __exit i2c_sch_exit(void) 3305bc12008SAlek Du { 3315bc12008SAlek Du pci_unregister_driver(&sch_driver); 3325bc12008SAlek Du } 3335bc12008SAlek Du 3345bc12008SAlek Du MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>"); 3355bc12008SAlek Du MODULE_DESCRIPTION("Intel SCH SMBus driver"); 3365bc12008SAlek Du MODULE_LICENSE("GPL"); 3375bc12008SAlek Du 3385bc12008SAlek Du module_init(i2c_sch_init); 3395bc12008SAlek Du module_exit(i2c_sch_exit); 340