2 * kernel/busses/i2c-prosavage.c
4 * i2c bus driver for S3/VIA 8365/8375 graphics processor.
5 * Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org>
6 * Based on code written by:
7 * Frodo Looijaard <frodol@dds.nl>,
8 * Philip Edelbrock <phil@netroedge.com>,
9 * Ralph Metzler <rjkm@thp.uni-koeln.de>, and
10 * Mark D. Studebaker <mdsxyz123@yahoo.com>
14 * Please read the lm_sensors documentation for details on use.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 /* 18-05-2003 HVE - created
32 * 14-06-2003 HVE - adapted for lm_sensors2
33 * 17-06-2003 HVE - linux 2.5.xx compatible
34 * 18-06-2003 HVE - codingstyle
35 * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx
36 * codingstyle, mmio enabled
38 * This driver interfaces to the I2C bus of the VIA north bridge embedded
39 * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips.
42 * S3/VIA KM266/VT8375 aka ProSavage8
43 * S3/VIA KM133/VT8365 aka Savage4
45 * Two serial busses are implemented:
46 * SERIAL1 - I2C serial communications interface
47 * SERIAL2 - DDC2 monitor communications interface
49 * Tested on a FX41 mainboard, see http://www.shuttle.com
53 * - integration with prosavage framebuffer device
54 * (Additional documentation needed :(
57 #include <linux/version.h>
58 #include <linux/module.h>
59 #include <linux/init.h>
60 #include <linux/pci.h>
61 #include <linux/i2c.h>
62 #include <linux/i2c-algo-bit.h>
68 * driver configuration
70 #define DRIVER_ID "i2c-prosavage"
71 #define DRIVER_VERSION "20030621"
73 #define ADAPTER_NAME(x) (x).name
81 struct i2c_adapter adap;
82 struct i2c_algo_bit_data algo;
87 struct s_i2c_bus i2c_bus[MAX_BUSSES];
94 #ifndef I2C_HW_B_S3VIA
95 #define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */
99 #define CYCLE_DELAY 10
100 #define TIMEOUT (HZ / 2)
104 * S3/VIA 8365/8375 registers
106 #ifndef PCI_VENDOR_ID_S3
107 #define PCI_VENDOR_ID_S3 0x5333
109 #ifndef PCI_DEVICE_ID_S3_SAVAGE4
110 #define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25
112 #ifndef PCI_DEVICE_ID_S3_PROSAVAGE8
113 #define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04
116 #define VGA_CR_IX 0x3d4
117 #define VGA_CR_DATA 0x3d5
119 #define CR_SERIAL1 0xa0 /* I2C serial communications interface */
120 #define MM_SERIAL1 0xff20
121 #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
123 /* based on vt8365 documentation */
124 #define I2C_ENAB 0x10
125 #define I2C_SCL_OUT 0x01
126 #define I2C_SDA_OUT 0x02
127 #define I2C_SCL_IN 0x04
128 #define I2C_SDA_IN 0x08
130 #define SET_CR_IX(p, val) *((p)->mmvga + VGA_CR_IX) = (u8)(val)
131 #define SET_CR_DATA(p, val) *((p)->mmvga + VGA_CR_DATA) = (u8)(val)
132 #define GET_CR_DATA(p) *((p)->mmvga + VGA_CR_DATA)
136 * Serial bus line handling
138 * serial communications register as parameter in private data
140 * TODO: locks with other code sections accessing video registers?
142 static void bit_s3via_setscl(void *bus, int val)
144 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
147 SET_CR_IX(p, p->i2c_reg);
158 static void bit_s3via_setsda(void *bus, int val)
160 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
163 SET_CR_IX(p, p->i2c_reg);
174 static int bit_s3via_getscl(void *bus)
176 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
178 SET_CR_IX(p, p->i2c_reg);
179 return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
182 static int bit_s3via_getsda(void *bus)
184 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
186 SET_CR_IX(p, p->i2c_reg);
187 return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
192 * adapter initialisation
194 static int i2c_register_bus(struct s_i2c_bus *p, u8 *mmvga, u32 i2c_reg)
197 p->adap.owner = THIS_MODULE;
198 p->adap.id = I2C_HW_B_S3VIA;
199 p->adap.algo_data = &p->algo;
200 p->algo.setsda = bit_s3via_setsda;
201 p->algo.setscl = bit_s3via_setscl;
202 p->algo.getsda = bit_s3via_getsda;
203 p->algo.getscl = bit_s3via_getscl;
204 p->algo.udelay = CYCLE_DELAY;
205 p->algo.mdelay = CYCLE_DELAY;
206 p->algo.timeout = TIMEOUT;
209 p->i2c_reg = i2c_reg;
211 ret = i2c_bit_add_bus(&p->adap);
224 static void __devexit prosavage_remove(struct pci_dev *dev)
226 struct s_i2c_chip *chip;
229 chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
234 for (i = MAX_BUSSES - 1; i >= 0; i--) {
235 if (chip->i2c_bus[i].adap_ok == 0)
238 ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
240 printk(DRIVER_ID ": %s not removed\n",
241 ADAPTER_NAME(chip->i2c_bus[i].adap));
252 * Detect chip and initialize it
254 static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
257 unsigned long base, len;
258 struct s_i2c_chip *chip;
259 struct s_i2c_bus *bus;
261 pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
262 chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
267 memset(chip, 0, sizeof(struct s_i2c_chip));
269 base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
270 len = dev->resource[0].end - base + 1;
271 chip->mmio = ioremap_nocache(base, len);
273 if (chip->mmio == NULL) {
274 printk (DRIVER_ID ": ioremap failed\n");
275 prosavage_remove(dev);
281 * Chip initialisation
283 /* Unlock Extended IO Space ??? */
287 * i2c bus registration
289 bus = &chip->i2c_bus[0];
290 snprintf(ADAPTER_NAME(bus->adap), sizeof(ADAPTER_NAME(bus->adap)),
291 "ProSavage I2C bus at %02x:%02x.%x",
292 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
293 ret = i2c_register_bus(bus, chip->mmio + 0x8000, CR_SERIAL1);
298 * ddc bus registration
300 bus = &chip->i2c_bus[1];
301 snprintf(ADAPTER_NAME(bus->adap), sizeof(ADAPTER_NAME(bus->adap)),
302 "ProSavage DDC bus at %02x:%02x.%x",
303 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
304 ret = i2c_register_bus(bus, chip->mmio + 0x8000, CR_SERIAL2);
310 printk (DRIVER_ID ": %s failed\n", ADAPTER_NAME(bus->adap));
311 prosavage_remove(dev);
317 * Data for PCI driver interface
319 static struct pci_device_id prosavage_pci_tbl[] = {
321 .vendor = PCI_VENDOR_ID_S3,
322 .device = PCI_DEVICE_ID_S3_SAVAGE4,
323 .subvendor = PCI_ANY_ID,
324 .subdevice = PCI_ANY_ID,
326 .vendor = PCI_VENDOR_ID_S3,
327 .device = PCI_DEVICE_ID_S3_PROSAVAGE8,
328 .subvendor = PCI_ANY_ID,
329 .subdevice = PCI_ANY_ID,
333 static struct pci_driver prosavage_driver = {
334 .name = "prosavage-smbus",
335 .id_table = prosavage_pci_tbl,
336 .probe = prosavage_probe,
337 .remove = __devexit_p(prosavage_remove),
340 static int __init i2c_prosavage_init(void)
342 printk(DRIVER_ID " version %s (%s)\n", I2C_VERSION, DRIVER_VERSION);
343 return pci_module_init(&prosavage_driver);
346 static void __exit i2c_prosavage_exit(void)
348 pci_unregister_driver(&prosavage_driver);
351 MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
352 MODULE_AUTHOR("Henk Vergonet");
353 MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
354 MODULE_LICENSE("GPL");
356 module_init (i2c_prosavage_init);
357 module_exit (i2c_prosavage_exit);