root/lm-sensors/trunk/kernel/busses/i2c-voodoo3.c @ 2772

Revision 2772, 6.8 KB (checked in by khali, 9 years ago)

Remove owner from i2c_adapter, restore inc_use and dec_use
instead.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware
3              monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
5    Philip Edelbrock <phil@netroedge.com>,
6    Ralph Metzler <rjkm@thp.uni-koeln.de>, and
7    Mark D. Studebaker <mdsxyz123@yahoo.com>
8   
9    Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
10    Simon Vogl
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25*/
26
27/* This interfaces to the I2C bus of the Voodoo3 to gain access to
28    the BT869 and possibly other I2C devices. */
29
30#include <linux/module.h>
31#include <linux/pci.h>
32#include <linux/i2c.h>
33#include <linux/i2c-algo-bit.h>
34#include <linux/init.h>
35#include <asm/io.h>
36#include <asm/param.h>  /* for HZ */
37#include "version.h"
38
39MODULE_LICENSE("GPL");
40
41/* the only registers we use */
42#define REG     0x78
43#define REG2    0x70
44
45/* bit locations in the register */
46#define DDC_ENAB        0x00040000
47#define DDC_SCL_OUT     0x00080000
48#define DDC_SDA_OUT     0x00100000
49#define DDC_SCL_IN      0x00200000
50#define DDC_SDA_IN      0x00400000
51#define I2C_ENAB        0x00800000
52#define I2C_SCL_OUT     0x01000000
53#define I2C_SDA_OUT     0x02000000
54#define I2C_SCL_IN      0x04000000
55#define I2C_SDA_IN      0x08000000
56
57/* initialization states */
58#define INIT2   0x2
59#define INIT3   0x4
60
61/* delays */
62#define CYCLE_DELAY     10
63#define TIMEOUT         (HZ / 2)
64
65
66static void config_v3(struct pci_dev *dev);
67
68static unsigned long ioaddr;
69
70/* The voo GPIO registers don't have individual masks for each bit
71   so we always have to read before writing. */
72
73static void bit_vooi2c_setscl(void *data, int val)
74{
75        unsigned int r;
76        r = readl(ioaddr + REG);
77        if(val)
78                r |= I2C_SCL_OUT;
79        else
80                r &= ~I2C_SCL_OUT;
81        writel(r, ioaddr + REG);
82        readl(ioaddr + REG);    /* flush posted write */
83}
84
85static void bit_vooi2c_setsda(void *data, int val)
86{
87        unsigned int r;
88        r = readl(ioaddr + REG);
89        if(val)
90                r |= I2C_SDA_OUT;
91        else
92                r &= ~I2C_SDA_OUT;
93        writel(r, ioaddr + REG);
94        readl(ioaddr + REG);    /* flush posted write */
95}
96
97/* The GPIO pins are open drain, so the pins always remain outputs.
98   We rely on the i2c-algo-bit routines to set the pins high before
99   reading the input from other chips. */
100
101static int bit_vooi2c_getscl(void *data)
102{
103        return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
104}
105
106static int bit_vooi2c_getsda(void *data)
107{
108        return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
109}
110
111static void bit_vooddc_setscl(void *data, int val)
112{
113        unsigned int r;
114        r = readl(ioaddr + REG);
115        if(val)
116                r |= DDC_SCL_OUT;
117        else
118                r &= ~DDC_SCL_OUT;
119        writel(r, ioaddr + REG);
120        readl(ioaddr + REG);    /* flush posted write */
121}
122
123static void bit_vooddc_setsda(void *data, int val)
124{
125        unsigned int r;
126        r = readl(ioaddr + REG);
127        if(val)
128                r |= DDC_SDA_OUT;
129        else
130                r &= ~DDC_SDA_OUT;
131        writel(r, ioaddr + REG);
132        readl(ioaddr + REG);    /* flush posted write */
133}
134
135static int bit_vooddc_getscl(void *data)
136{
137        return (0 != (readl(ioaddr + REG) & DDC_SCL_IN));
138}
139
140static int bit_vooddc_getsda(void *data)
141{
142        return (0 != (readl(ioaddr + REG) & DDC_SDA_IN));
143}
144
145
146/* Configures the chip */
147
148void config_v3(struct pci_dev *dev)
149{
150        unsigned int cadr;
151
152        /* map Voodoo3 memory */
153        cadr = dev->resource[0].start;
154        cadr &= PCI_BASE_ADDRESS_MEM_MASK;
155        ioaddr = (unsigned long)ioremap_nocache(cadr, 0x1000);
156        if(ioaddr) {
157                writel(0x8160, ioaddr + REG2);
158                writel(0xcffc0020, ioaddr + REG);
159                printk("i2c-voodoo3: Using Banshee/Voodoo3 at 0x%lx\n", ioaddr);
160        }
161}
162
163static void voodoo3_inc(struct i2c_adapter *adapter)
164{
165#ifdef MODULE
166        MOD_INC_USE_COUNT;
167#endif
168}
169
170void voodoo3_dec(struct i2c_adapter *adapter)
171{
172#ifdef MODULE
173        MOD_DEC_USE_COUNT;
174#endif
175}
176
177static struct i2c_algo_bit_data voo_i2c_bit_data = {
178        .setsda         = bit_vooi2c_setsda,
179        .setscl         = bit_vooi2c_setscl,
180        .getsda         = bit_vooi2c_getsda,
181        .getscl         = bit_vooi2c_getscl,
182        .udelay         = CYCLE_DELAY,
183        .mdelay         = CYCLE_DELAY,
184        .timeout        = TIMEOUT
185};
186
187static struct i2c_adapter voodoo3_i2c_adapter = {
188        .name           = "I2C Voodoo3/Banshee adapter",
189        .id             = I2C_HW_B_VOO,
190        .algo_data      = &voo_i2c_bit_data,
191        .inc_use        = voodoo3_inc,
192        .dec_use        = voodoo3_dec,
193};
194
195static struct i2c_algo_bit_data voo_ddc_bit_data = {
196        .setsda         = bit_vooddc_setsda,
197        .setscl         = bit_vooddc_setscl,
198        .getsda         = bit_vooddc_getsda,
199        .getscl         = bit_vooddc_getscl,
200        .udelay         = CYCLE_DELAY,
201        .mdelay         = CYCLE_DELAY,
202        .timeout        = TIMEOUT
203};
204
205static struct i2c_adapter voodoo3_ddc_adapter = {
206        .name           = "DDC Voodoo3/Banshee adapter",
207        .id             = I2C_HW_B_VOO,
208        .algo_data      = &voo_ddc_bit_data,
209        .inc_use        = voodoo3_inc,
210        .dec_use        = voodoo3_dec,
211};
212
213
214static struct pci_device_id voodoo3_ids[] __devinitdata = {
215        {
216                .vendor =       PCI_VENDOR_ID_3DFX,
217                .device =       PCI_DEVICE_ID_3DFX_VOODOO3,
218                .subvendor =    PCI_ANY_ID,
219                .subdevice =    PCI_ANY_ID,
220        },
221        {
222                .vendor =       PCI_VENDOR_ID_3DFX,
223                .device =       PCI_DEVICE_ID_3DFX_BANSHEE,
224                .subvendor =    PCI_ANY_ID,
225                .subdevice =    PCI_ANY_ID,
226        },
227        { 0, }
228};
229
230static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id)
231{
232        int retval;
233
234        printk("voodoo3: in probe\n");
235        config_v3(dev);
236        retval = i2c_bit_add_bus(&voodoo3_i2c_adapter);
237        if(retval)
238                return retval;
239        retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
240        if(retval)
241                i2c_bit_del_bus(&voodoo3_i2c_adapter);
242        return retval;
243}
244
245static void __devexit voodoo3_remove(struct pci_dev *dev)
246{
247        i2c_bit_del_bus(&voodoo3_i2c_adapter);
248        i2c_bit_del_bus(&voodoo3_ddc_adapter);
249}
250
251
252/* Don't register driver to avoid driver conflicts */
253/*
254static struct pci_driver voodoo3_driver = {
255        .name           = "voodoo3 smbus",
256        .id_table       = voodoo3_ids,
257        .probe          = voodoo3_probe,
258        .remove         = __devexit_p(voodoo3_remove),
259};
260*/
261
262static int __init i2c_voodoo3_init(void)
263{
264        struct pci_dev *dev;
265        const struct pci_device_id *id;
266
267        printk("i2c-voodoo3.o version %s (%s)\n", LM_VERSION, LM_DATE);
268/*
269        return pci_module_init(&voodoo3_driver);
270*/
271        pci_for_each_dev(dev) {
272                id = pci_match_device(voodoo3_ids, dev);
273                if(id)
274                        if(voodoo3_probe(dev, id) >= 0)
275                                return 0;
276        }
277        return -ENODEV;
278}
279
280
281static void __exit i2c_voodoo3_exit(void)
282{
283/*
284        pci_unregister_driver(&voodoo3_driver);
285*/
286        voodoo3_remove(NULL);
287        iounmap((void *)ioaddr);
288}
289
290
291MODULE_AUTHOR
292    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
293MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver");
294
295module_init(i2c_voodoo3_init);
296module_exit(i2c_voodoo3_exit);
Note: See TracBrowser for help on using the browser.