diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c')
-rw-r--r-- | ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c deleted file mode 100644 index eb778bf1..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> - - Shamelessly ripped from i2c-piix4.c: - - Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> - - 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. -*/ - -/* - 2002-04-08: Added nForce support. (Csaba Halasz) - 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil) - 2002-12-28: Rewritten into something that resembles a Linux driver (hch) - 2003-11-29: Added back AMD8111 removed by the previous rewrite. - (Philip Pokorny) -*/ - -/* - Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce - 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/acpi.h> -#include <linux/io.h> - -/* AMD756 SMBus address offsets */ -#define SMB_ADDR_OFFSET 0xE0 -#define SMB_IOSIZE 16 -#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) -#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) -#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) -#define SMB_HOST_DATA (0x6 + amd756_ioport) -#define SMB_HOST_COMMAND (0x8 + amd756_ioport) -#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) -#define SMB_HAS_DATA (0xA + amd756_ioport) -#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) -#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) -#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) - -/* PCI Address Constants */ - -/* address of I/O space */ -#define SMBBA 0x058 /* mh */ -#define SMBBANFORCE 0x014 - -/* general configuration */ -#define SMBGCFG 0x041 /* mh */ - -/* silicon revision code */ -#define SMBREV 0x008 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* AMD756 constants */ -#define AMD756_QUICK 0x00 -#define AMD756_BYTE 0x01 -#define AMD756_BYTE_DATA 0x02 -#define AMD756_WORD_DATA 0x03 -#define AMD756_PROCESS_CALL 0x04 -#define AMD756_BLOCK_DATA 0x05 - -static struct pci_driver amd756_driver; -static unsigned short amd756_ioport; - -/* - SMBUS event = I/O 28-29 bit 11 - see E0 for the status bits and enabled in E2 - -*/ -#define GS_ABRT_STS (1 << 0) -#define GS_COL_STS (1 << 1) -#define GS_PRERR_STS (1 << 2) -#define GS_HST_STS (1 << 3) -#define GS_HCYC_STS (1 << 4) -#define GS_TO_STS (1 << 5) -#define GS_SMB_STS (1 << 11) - -#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ - GS_HCYC_STS | GS_TO_STS ) - -#define GE_CYC_TYPE_MASK (7) -#define GE_HOST_STC (1 << 3) -#define GE_ABORT (1 << 5) - - -static int amd756_transaction(struct i2c_adapter *adap) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " - "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), - inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), - inb_p(SMB_HOST_DATA)); - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { - dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp); - do { - msleep(1); - temp = inw_p(SMB_GLOBAL_STATUS); - } while ((temp & (GS_HST_STS | GS_SMB_STS)) && - (timeout++ < MAX_TIMEOUT)); - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp); - goto abort; - } - timeout = 0; - } - - /* start the transaction by setting the start bit */ - outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE); - - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - temp = inw_p(SMB_GLOBAL_STATUS); - } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "Completion timeout!\n"); - goto abort; - } - - if (temp & GS_PRERR_STS) { - result = -ENXIO; - dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); - } - - if (temp & GS_COL_STS) { - result = -EIO; - dev_warn(&adap->dev, "SMBus collision!\n"); - } - - if (temp & GS_TO_STS) { - result = -ETIMEDOUT; - dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); - } - - if (temp & GS_HCYC_STS) - dev_dbg(&adap->dev, "SMBus protocol success!\n"); - - outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - -#ifdef DEBUG - if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { - dev_dbg(&adap->dev, - "Failed reset at end of transaction (%04x)\n", temp); - } -#endif - - dev_dbg(&adap->dev, - "Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", - inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), - inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); - - return result; - - abort: - dev_warn(&adap->dev, "Sending abort\n"); - outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); - msleep(100); - outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - return -EIO; -} - -/* Return negative errno on error. */ -static s32 amd756_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - int i, len; - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - size = AMD756_QUICK; - break; - case I2C_SMBUS_BYTE: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMB_HOST_DATA); - size = AMD756_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) - outw_p(data->byte, SMB_HOST_DATA); - size = AMD756_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) - outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ - size = AMD756_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - if (len > 32) - len = 32; - outw_p(len, SMB_HOST_DATA); - /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], - SMB_HOST_BLOCK_DATA); - } - size = AMD756_BLOCK_DATA; - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - /* How about enabling interrupts... */ - outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); - - status = amd756_transaction(adap); - if (status) - return status; - - if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) - return 0; - - - switch (size) { - case AMD756_BYTE: - data->byte = inw_p(SMB_HOST_DATA); - break; - case AMD756_BYTE_DATA: - data->byte = inw_p(SMB_HOST_DATA); - break; - case AMD756_WORD_DATA: - data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ - break; - case AMD756_BLOCK_DATA: - data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f; - if(data->block[0] > 32) - data->block[0] = 32; - /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMB_HOST_BLOCK_DATA); - break; - } - - return 0; -} - -static u32 amd756_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 = amd756_access, - .functionality = amd756_func, -}; - -struct i2c_adapter amd756_smbus = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 }; -static const char* chipname[] = { - "AMD756", "AMD766", "AMD768", - "nVidia nForce", "AMD8111", -}; - -static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), - .driver_data = AMD756 }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), - .driver_data = AMD766 }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443), - .driver_data = AMD768 }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), - .driver_data = AMD8111 }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS), - .driver_data = NFORCE }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, amd756_ids); - -static int __devinit amd756_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int nforce = (id->driver_data == NFORCE); - int error; - u8 temp; - - if (amd756_ioport) { - dev_err(&pdev->dev, "Only one device supported " - "(you have a strange motherboard, btw)\n"); - return -ENODEV; - } - - if (nforce) { - if (PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport); - amd756_ioport &= 0xfffc; - } else { /* amd */ - if (PCI_FUNC(pdev->devfn) != 3) - return -ENODEV; - - pci_read_config_byte(pdev, SMBGCFG, &temp); - if ((temp & 128) == 0) { - dev_err(&pdev->dev, - "Error: SMBus controller I/O not enabled!\n"); - return -ENODEV; - } - - /* Determine the address of the SMBus areas */ - /* Technically it is a dword but... */ - pci_read_config_word(pdev, SMBBA, &amd756_ioport); - amd756_ioport &= 0xff00; - amd756_ioport += SMB_ADDR_OFFSET; - } - - error = acpi_check_region(amd756_ioport, SMB_IOSIZE, - amd756_driver.name); - if (error) - return -ENODEV; - - if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { - dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", - amd756_ioport); - return -ENODEV; - } - - pci_read_config_byte(pdev, SMBREV, &temp); - dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport); - - /* set up the sysfs linkage to our parent device */ - amd756_smbus.dev.parent = &pdev->dev; - - snprintf(amd756_smbus.name, sizeof(amd756_smbus.name), - "SMBus %s adapter at %04x", chipname[id->driver_data], - amd756_ioport); - - error = i2c_add_adapter(&amd756_smbus); - if (error) { - dev_err(&pdev->dev, - "Adapter registration failed, module not inserted\n"); - goto out_err; - } - - return 0; - - out_err: - release_region(amd756_ioport, SMB_IOSIZE); - return error; -} - -static void __devexit amd756_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&amd756_smbus); - release_region(amd756_ioport, SMB_IOSIZE); -} - -static struct pci_driver amd756_driver = { - .name = "amd756_smbus", - .id_table = amd756_ids, - .probe = amd756_probe, - .remove = __devexit_p(amd756_remove), -}; - -static int __init amd756_init(void) -{ - return pci_register_driver(&amd756_driver); -} - -static void __exit amd756_exit(void) -{ - pci_unregister_driver(&amd756_driver); -} - -MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>"); -MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(amd756_smbus); - -module_init(amd756_init) -module_exit(amd756_exit) |