Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20 203 lines 5.3 kB view raw
1/* 2 i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware 3 monitoring 4 Copyright (C) 1998-2003 The LM Sensors Team 5 Alexander Wold <awold@bigfoot.com> 6 Mark D. Studebaker <mdsxyz123@yahoo.com> 7 8 Based on i2c-voodoo3.c. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23*/ 24 25/* This interfaces to the I2C bus of the Savage4 to gain access to 26 the BT869 and possibly other I2C devices. The DDC bus is not 27 yet supported because its register is not memory-mapped. 28 However we leave the DDC code here, commented out, to make 29 it easier to add later. 30*/ 31 32#include <linux/kernel.h> 33#include <linux/module.h> 34#include <linux/init.h> 35#include <linux/pci.h> 36#include <linux/i2c.h> 37#include <linux/i2c-algo-bit.h> 38#include <asm/io.h> 39 40/* 3DFX defines */ 41#define PCI_CHIP_SAVAGE3D 0x8A20 42#define PCI_CHIP_SAVAGE3D_MV 0x8A21 43#define PCI_CHIP_SAVAGE4 0x8A22 44#define PCI_CHIP_SAVAGE2000 0x9102 45#define PCI_CHIP_PROSAVAGE_PM 0x8A25 46#define PCI_CHIP_PROSAVAGE_KM 0x8A26 47#define PCI_CHIP_SAVAGE_MX_MV 0x8c10 48#define PCI_CHIP_SAVAGE_MX 0x8c11 49#define PCI_CHIP_SAVAGE_IX_MV 0x8c12 50#define PCI_CHIP_SAVAGE_IX 0x8c13 51 52#define REG 0xff20 /* Serial Port 1 Register */ 53 54/* bit locations in the register */ 55#define DDC_ENAB 0x00040000 56#define DDC_SCL_OUT 0x00080000 57#define DDC_SDA_OUT 0x00100000 58#define DDC_SCL_IN 0x00200000 59#define DDC_SDA_IN 0x00400000 60#define I2C_ENAB 0x00000020 61#define I2C_SCL_OUT 0x00000001 62#define I2C_SDA_OUT 0x00000002 63#define I2C_SCL_IN 0x00000008 64#define I2C_SDA_IN 0x00000010 65 66/* initialization states */ 67#define INIT2 0x20 68#define INIT3 0x04 69 70/* delays */ 71#define CYCLE_DELAY 10 72#define TIMEOUT (HZ / 2) 73 74 75static void __iomem *ioaddr; 76 77/* The sav GPIO registers don't have individual masks for each bit 78 so we always have to read before writing. */ 79 80static void bit_savi2c_setscl(void *data, int val) 81{ 82 unsigned int r; 83 r = readl(ioaddr + REG); 84 if(val) 85 r |= I2C_SCL_OUT; 86 else 87 r &= ~I2C_SCL_OUT; 88 writel(r, ioaddr + REG); 89 readl(ioaddr + REG); /* flush posted write */ 90} 91 92static void bit_savi2c_setsda(void *data, int val) 93{ 94 unsigned int r; 95 r = readl(ioaddr + REG); 96 if(val) 97 r |= I2C_SDA_OUT; 98 else 99 r &= ~I2C_SDA_OUT; 100 writel(r, ioaddr + REG); 101 readl(ioaddr + REG); /* flush posted write */ 102} 103 104/* The GPIO pins are open drain, so the pins always remain outputs. 105 We rely on the i2c-algo-bit routines to set the pins high before 106 reading the input from other chips. */ 107 108static int bit_savi2c_getscl(void *data) 109{ 110 return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); 111} 112 113static int bit_savi2c_getsda(void *data) 114{ 115 return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); 116} 117 118/* Configures the chip */ 119 120static int config_s4(struct pci_dev *dev) 121{ 122 unsigned long cadr; 123 124 /* map memory */ 125 cadr = dev->resource[0].start; 126 cadr &= PCI_BASE_ADDRESS_MEM_MASK; 127 ioaddr = ioremap_nocache(cadr, 0x0080000); 128 if (ioaddr) { 129 /* writel(0x8160, ioaddr + REG2); */ 130 writel(0x00000020, ioaddr + REG); 131 dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr); 132 return 0; 133 } 134 return -ENODEV; 135} 136 137static struct i2c_algo_bit_data sav_i2c_bit_data = { 138 .setsda = bit_savi2c_setsda, 139 .setscl = bit_savi2c_setscl, 140 .getsda = bit_savi2c_getsda, 141 .getscl = bit_savi2c_getscl, 142 .udelay = CYCLE_DELAY, 143 .timeout = TIMEOUT 144}; 145 146static struct i2c_adapter savage4_i2c_adapter = { 147 .owner = THIS_MODULE, 148 .name = "I2C Savage4 adapter", 149 .algo_data = &sav_i2c_bit_data, 150}; 151 152static struct pci_device_id savage4_ids[] __devinitdata = { 153 { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) }, 154 { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) }, 155 { 0, } 156}; 157 158MODULE_DEVICE_TABLE (pci, savage4_ids); 159 160static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) 161{ 162 int retval; 163 164 retval = config_s4(dev); 165 if (retval) 166 return retval; 167 168 /* set up the sysfs linkage to our parent device */ 169 savage4_i2c_adapter.dev.parent = &dev->dev; 170 171 return i2c_bit_add_bus(&savage4_i2c_adapter); 172} 173 174static void __devexit savage4_remove(struct pci_dev *dev) 175{ 176 i2c_del_adapter(&savage4_i2c_adapter); 177 iounmap(ioaddr); 178} 179 180static struct pci_driver savage4_driver = { 181 .name = "savage4_smbus", 182 .id_table = savage4_ids, 183 .probe = savage4_probe, 184 .remove = __devexit_p(savage4_remove), 185}; 186 187static int __init i2c_savage4_init(void) 188{ 189 return pci_register_driver(&savage4_driver); 190} 191 192static void __exit i2c_savage4_exit(void) 193{ 194 pci_unregister_driver(&savage4_driver); 195} 196 197MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> " 198 "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); 199MODULE_DESCRIPTION("Savage4 I2C/SMBus driver"); 200MODULE_LICENSE("GPL"); 201 202module_init(i2c_savage4_init); 203module_exit(i2c_savage4_exit);