Merge /spare/repo/linux-2.6/
[pandora-kernel.git] / drivers / i2c / busses / i2c-prosavage.c
1 /*
2  *    kernel/busses/i2c-prosavage.c
3  *
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
13  *
14  *    Please read the lm_sensors documentation for details on use.
15  *
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.
20  *
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.
25  *
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.
29  *
30  */
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
37  *
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.
40  *
41  *  Graphics cores:
42  *   S3/VIA KM266/VT8375 aka ProSavage8
43  *   S3/VIA KM133/VT8365 aka Savage4
44  *
45  *  Two serial busses are implemented:
46  *   SERIAL1 - I2C serial communications interface
47  *   SERIAL2 - DDC2 monitor communications interface
48  *
49  *  Tested on a FX41 mainboard, see http://www.shuttle.com
50  * 
51  *
52  *  TODO:
53  *  - integration with prosavage framebuffer device
54  *    (Additional documentation needed :(
55  */
56
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>
63
64 /*
65  * driver configuration
66  */
67 #define MAX_BUSSES      2
68
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;
75 };
76
77 struct s_i2c_chip {
78         void __iomem *mmio;
79         struct s_i2c_bus        i2c_bus[MAX_BUSSES];
80 };
81
82
83 /*
84  * i2c configuration
85  */
86 #ifndef I2C_HW_B_S3VIA
87 #define I2C_HW_B_S3VIA  0x18    /* S3VIA ProSavage adapter              */
88 #endif
89
90 /* delays */
91 #define CYCLE_DELAY     10
92 #define TIMEOUT         (HZ / 2)
93
94
95 /* 
96  * S3/VIA 8365/8375 registers
97  */
98 #define VGA_CR_IX       0x3d4
99 #define VGA_CR_DATA     0x3d5
100
101 #define CR_SERIAL1      0xa0    /* I2C serial communications interface */
102 #define MM_SERIAL1      0xff20
103 #define CR_SERIAL2      0xb1    /* DDC2 monitor communications interface */
104
105 /* based on vt8365 documentation */
106 #define I2C_ENAB        0x10
107 #define I2C_SCL_OUT     0x01
108 #define I2C_SDA_OUT     0x02
109 #define I2C_SCL_IN      0x04
110 #define I2C_SDA_IN      0x08
111
112 #define SET_CR_IX(p, val)       writeb((val), (p)->mmvga + VGA_CR_IX)
113 #define SET_CR_DATA(p, val)     writeb((val), (p)->mmvga + VGA_CR_DATA)
114 #define GET_CR_DATA(p)          readb((p)->mmvga + VGA_CR_DATA)
115
116
117 /*
118  * Serial bus line handling
119  *
120  * serial communications register as parameter in private data
121  *
122  * TODO: locks with other code sections accessing video registers?
123  */
124 static void bit_s3via_setscl(void *bus, int val)
125 {
126         struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
127         unsigned int r;
128
129         SET_CR_IX(p, p->i2c_reg);
130         r = GET_CR_DATA(p);
131         r |= I2C_ENAB;
132         if (val) {
133                 r |= I2C_SCL_OUT;
134         } else {
135                 r &= ~I2C_SCL_OUT;
136         }
137         SET_CR_DATA(p, r);
138 }
139
140 static void bit_s3via_setsda(void *bus, int val)
141 {
142         struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
143         unsigned int r;
144         
145         SET_CR_IX(p, p->i2c_reg);
146         r = GET_CR_DATA(p);
147         r |= I2C_ENAB;
148         if (val) {
149                 r |= I2C_SDA_OUT;
150         } else {
151                 r &= ~I2C_SDA_OUT;
152         }
153         SET_CR_DATA(p, r);
154 }
155
156 static int bit_s3via_getscl(void *bus)
157 {
158         struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
159
160         SET_CR_IX(p, p->i2c_reg);
161         return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
162 }
163
164 static int bit_s3via_getsda(void *bus)
165 {
166         struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
167
168         SET_CR_IX(p, p->i2c_reg);
169         return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
170 }
171
172
173 /*
174  * adapter initialisation
175  */
176 static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
177 {
178         int ret;
179         p->adap.owner     = THIS_MODULE;
180         p->adap.id        = I2C_HW_B_S3VIA;
181         p->adap.algo_data = &p->algo;
182         p->adap.dev.parent = &dev->dev;
183         p->algo.setsda    = bit_s3via_setsda;
184         p->algo.setscl    = bit_s3via_setscl;
185         p->algo.getsda    = bit_s3via_getsda;
186         p->algo.getscl    = bit_s3via_getscl;
187         p->algo.udelay    = CYCLE_DELAY;
188         p->algo.mdelay    = CYCLE_DELAY;
189         p->algo.timeout   = TIMEOUT;
190         p->algo.data      = p;
191         p->mmvga          = mmvga;
192         p->i2c_reg        = i2c_reg;
193     
194         ret = i2c_bit_add_bus(&p->adap);
195         if (ret) {
196                 return ret;
197         }
198
199         p->adap_ok = 1;
200         return 0;
201 }
202
203
204 /*
205  * Cleanup stuff
206  */
207 static void prosavage_remove(struct pci_dev *dev)
208 {
209         struct s_i2c_chip *chip;
210         int i, ret;
211
212         chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
213
214         if (!chip) {
215                 return;
216         }
217         for (i = MAX_BUSSES - 1; i >= 0; i--) {
218                 if (chip->i2c_bus[i].adap_ok == 0)
219                         continue;
220
221                 ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
222                 if (ret) {
223                         dev_err(&dev->dev, "%s not removed\n",
224                                 chip->i2c_bus[i].adap.name);
225                 }
226         }
227         if (chip->mmio) {
228                 iounmap(chip->mmio);
229         }
230         kfree(chip);
231 }
232
233
234 /*
235  * Detect chip and initialize it
236  */
237 static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
238 {
239         int ret;
240         unsigned long base, len;
241         struct s_i2c_chip *chip;
242         struct s_i2c_bus  *bus;
243
244         pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); 
245         chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
246         if (chip == NULL) {
247                 return -ENOMEM;
248         }
249
250         memset(chip, 0, sizeof(struct s_i2c_chip));
251
252         base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
253         len  = dev->resource[0].end - base + 1;
254         chip->mmio = ioremap_nocache(base, len);
255
256         if (chip->mmio == NULL) {
257                 dev_err(&dev->dev, "ioremap failed\n");
258                 prosavage_remove(dev);
259                 return -ENODEV;
260         }
261
262
263         /*
264          * Chip initialisation
265          */
266         /* Unlock Extended IO Space ??? */
267
268
269         /*
270          * i2c bus registration
271          */
272         bus = &chip->i2c_bus[0];
273         snprintf(bus->adap.name, sizeof(bus->adap.name),
274                 "ProSavage I2C bus at %02x:%02x.%x",
275                 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
276         ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
277         if (ret) {
278                 goto err_adap;
279         }
280         /*
281          * ddc bus registration
282          */
283         bus = &chip->i2c_bus[1];
284         snprintf(bus->adap.name, sizeof(bus->adap.name),
285                 "ProSavage DDC bus at %02x:%02x.%x",
286                 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
287         ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
288         if (ret) {
289                 goto err_adap;
290         }
291         return 0;
292 err_adap:
293         dev_err(&dev->dev, "%s failed\n", bus->adap.name);
294         prosavage_remove(dev);
295         return ret;
296 }
297
298
299 /*
300  * Data for PCI driver interface
301  */
302 static struct pci_device_id prosavage_pci_tbl[] = {
303         { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
304         { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
305         { 0, },
306 };
307
308 MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
309
310 static struct pci_driver prosavage_driver = {
311         .name           =       "prosavage_smbus",
312         .id_table       =       prosavage_pci_tbl,
313         .probe          =       prosavage_probe,
314         .remove         =       prosavage_remove,
315 };
316
317 static int __init i2c_prosavage_init(void)
318 {
319         return pci_register_driver(&prosavage_driver);
320 }
321
322 static void __exit i2c_prosavage_exit(void)
323 {
324         pci_unregister_driver(&prosavage_driver);
325 }
326
327 MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
328 MODULE_AUTHOR("Henk Vergonet");
329 MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
330 MODULE_LICENSE("GPL");
331
332 module_init (i2c_prosavage_init);
333 module_exit (i2c_prosavage_exit);