[PATCH] PCI: removed unneeded .owner field from struct pci_driver
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / i2c / busses / i2c-prosavage.c
blob9479525892e3e337d0872eef7f630041776bf0ff
1 /*
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>
11 * Simon Vogl
12 * and others
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.
41 * Graphics cores:
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
52 * TODO:
53 * - integration with prosavage framebuffer device
54 * (Additional documentation needed :(
57 #include <linux/module.h>
58 #include <linux/init.h>
59 #include <linux/pci.h>
60 #include <linux/i2c.h>
61 #include <linux/i2c-algo-bit.h>
62 #include <asm/io.h>
65 * driver configuration
67 #define MAX_BUSSES 2
69 struct s_i2c_bus {
70 void __iomem *mmvga;
71 int i2c_reg;
72 int adap_ok;
73 struct i2c_adapter adap;
74 struct i2c_algo_bit_data algo;
77 struct s_i2c_chip {
78 void __iomem *mmio;
79 struct s_i2c_bus i2c_bus[MAX_BUSSES];
84 * i2c configuration
86 #define CYCLE_DELAY 10
87 #define TIMEOUT (HZ / 2)
90 /*
91 * S3/VIA 8365/8375 registers
93 #define VGA_CR_IX 0x3d4
94 #define VGA_CR_DATA 0x3d5
96 #define CR_SERIAL1 0xa0 /* I2C serial communications interface */
97 #define MM_SERIAL1 0xff20
98 #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
100 /* based on vt8365 documentation */
101 #define I2C_ENAB 0x10
102 #define I2C_SCL_OUT 0x01
103 #define I2C_SDA_OUT 0x02
104 #define I2C_SCL_IN 0x04
105 #define I2C_SDA_IN 0x08
107 #define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX)
108 #define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA)
109 #define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA)
113 * Serial bus line handling
115 * serial communications register as parameter in private data
117 * TODO: locks with other code sections accessing video registers?
119 static void bit_s3via_setscl(void *bus, int val)
121 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
122 unsigned int r;
124 SET_CR_IX(p, p->i2c_reg);
125 r = GET_CR_DATA(p);
126 r |= I2C_ENAB;
127 if (val) {
128 r |= I2C_SCL_OUT;
129 } else {
130 r &= ~I2C_SCL_OUT;
132 SET_CR_DATA(p, r);
135 static void bit_s3via_setsda(void *bus, int val)
137 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
138 unsigned int r;
140 SET_CR_IX(p, p->i2c_reg);
141 r = GET_CR_DATA(p);
142 r |= I2C_ENAB;
143 if (val) {
144 r |= I2C_SDA_OUT;
145 } else {
146 r &= ~I2C_SDA_OUT;
148 SET_CR_DATA(p, r);
151 static int bit_s3via_getscl(void *bus)
153 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
155 SET_CR_IX(p, p->i2c_reg);
156 return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
159 static int bit_s3via_getsda(void *bus)
161 struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
163 SET_CR_IX(p, p->i2c_reg);
164 return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
169 * adapter initialisation
171 static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
173 int ret;
174 p->adap.owner = THIS_MODULE;
175 p->adap.id = I2C_HW_B_S3VIA;
176 p->adap.algo_data = &p->algo;
177 p->adap.dev.parent = &dev->dev;
178 p->algo.setsda = bit_s3via_setsda;
179 p->algo.setscl = bit_s3via_setscl;
180 p->algo.getsda = bit_s3via_getsda;
181 p->algo.getscl = bit_s3via_getscl;
182 p->algo.udelay = CYCLE_DELAY;
183 p->algo.mdelay = CYCLE_DELAY;
184 p->algo.timeout = TIMEOUT;
185 p->algo.data = p;
186 p->mmvga = mmvga;
187 p->i2c_reg = i2c_reg;
189 ret = i2c_bit_add_bus(&p->adap);
190 if (ret) {
191 return ret;
194 p->adap_ok = 1;
195 return 0;
200 * Cleanup stuff
202 static void prosavage_remove(struct pci_dev *dev)
204 struct s_i2c_chip *chip;
205 int i, ret;
207 chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
209 if (!chip) {
210 return;
212 for (i = MAX_BUSSES - 1; i >= 0; i--) {
213 if (chip->i2c_bus[i].adap_ok == 0)
214 continue;
216 ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
217 if (ret) {
218 dev_err(&dev->dev, "%s not removed\n",
219 chip->i2c_bus[i].adap.name);
222 if (chip->mmio) {
223 iounmap(chip->mmio);
225 kfree(chip);
230 * Detect chip and initialize it
232 static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
234 int ret;
235 unsigned long base, len;
236 struct s_i2c_chip *chip;
237 struct s_i2c_bus *bus;
239 pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
240 chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
241 if (chip == NULL) {
242 return -ENOMEM;
245 base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
246 len = dev->resource[0].end - base + 1;
247 chip->mmio = ioremap_nocache(base, len);
249 if (chip->mmio == NULL) {
250 dev_err(&dev->dev, "ioremap failed\n");
251 prosavage_remove(dev);
252 return -ENODEV;
257 * Chip initialisation
259 /* Unlock Extended IO Space ??? */
263 * i2c bus registration
265 bus = &chip->i2c_bus[0];
266 snprintf(bus->adap.name, sizeof(bus->adap.name),
267 "ProSavage I2C bus at %02x:%02x.%x",
268 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
269 ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
270 if (ret) {
271 goto err_adap;
274 * ddc bus registration
276 bus = &chip->i2c_bus[1];
277 snprintf(bus->adap.name, sizeof(bus->adap.name),
278 "ProSavage DDC bus at %02x:%02x.%x",
279 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
280 ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
281 if (ret) {
282 goto err_adap;
284 return 0;
285 err_adap:
286 dev_err(&dev->dev, "%s failed\n", bus->adap.name);
287 prosavage_remove(dev);
288 return ret;
293 * Data for PCI driver interface
295 static struct pci_device_id prosavage_pci_tbl[] = {
296 { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
297 { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
298 { 0, },
301 MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
303 static struct pci_driver prosavage_driver = {
304 .name = "prosavage_smbus",
305 .id_table = prosavage_pci_tbl,
306 .probe = prosavage_probe,
307 .remove = prosavage_remove,
310 static int __init i2c_prosavage_init(void)
312 return pci_register_driver(&prosavage_driver);
315 static void __exit i2c_prosavage_exit(void)
317 pci_unregister_driver(&prosavage_driver);
320 MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
321 MODULE_AUTHOR("Henk Vergonet");
322 MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
323 MODULE_LICENSE("GPL");
325 module_init (i2c_prosavage_init);
326 module_exit (i2c_prosavage_exit);