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

Revision 1201, 7.8 KB (checked in by mds, 13 years ago)

Add MODULE_LICENSE("GPL") to all modules

  • 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/version.h>
31#include <linux/module.h>
32#include <linux/pci.h>
33#include <asm/io.h>
34#include <linux/i2c.h>
35#include <linux/i2c-algo-bit.h>
36#include "version.h"
37#include <linux/init.h>
38
39#ifdef MODULE_LICENSE
40MODULE_LICENSE("GPL");
41#endif
42
43/* 3DFX defines */
44#ifndef PCI_DEVICE_ID_3DFX_VOODOO3
45#define PCI_DEVICE_ID_3DFX_VOODOO3 0x05
46#endif
47#ifndef PCI_DEVICE_ID_3DFX_BANSHEE
48#define PCI_DEVICE_ID_3DFX_BANSHEE 0x03
49#endif
50
51/* the only registers we use */
52#define REG     0x78
53#define REG2    0x70
54
55/* bit locations in the register */
56#define DDC_ENAB        0x00040000
57#define DDC_SCL_OUT     0x00080000
58#define DDC_SDA_OUT     0x00100000
59#define DDC_SCL_IN      0x00200000
60#define DDC_SDA_IN      0x00400000
61#define I2C_ENAB        0x00800000
62#define I2C_SCL_OUT     0x01000000
63#define I2C_SDA_OUT     0x02000000
64#define I2C_SCL_IN      0x04000000
65#define I2C_SDA_IN      0x08000000
66
67/* initialization states */
68#define INIT2   0x2
69#define INIT3   0x4
70
71/* delays */
72#define CYCLE_DELAY     10
73#define TIMEOUT         50
74
75#ifdef MODULE
76static
77#else
78extern
79#endif
80int __init i2c_voodoo3_init(void);
81static int __init voodoo3_cleanup(void);
82static int voodoo3_setup(void);
83static void config_v3(struct pci_dev *dev);
84static void voodoo3_inc(struct i2c_adapter *adapter);
85static void voodoo3_dec(struct i2c_adapter *adapter);
86
87#ifdef MODULE
88extern int init_module(void);
89extern int cleanup_module(void);
90#endif                          /* MODULE */
91
92
93static int __initdata voodoo3_initialized;
94static unsigned char *mem;
95
96extern inline void outlong(unsigned int dat)
97{
98        *((unsigned int *) (mem + REG)) = dat;
99}
100
101extern inline unsigned int readlong(void)
102{
103        return *((unsigned int *) (mem + REG));
104}
105
106/* The voo GPIO registers don't have individual masks for each bit
107   so we always have to read before writing. */
108
109static void bit_vooi2c_setscl(void *data, int val)
110{
111        unsigned int r;
112        r = readlong();
113        if(val)
114                r |= I2C_SCL_OUT;
115        else
116                r &= ~I2C_SCL_OUT;
117        outlong(r);
118}
119
120static void bit_vooi2c_setsda(void *data, int val)
121{
122        unsigned int r;
123        r = readlong();
124        if(val)
125                r |= I2C_SDA_OUT;
126        else
127                r &= ~I2C_SDA_OUT;
128        outlong(r);
129}
130
131/* The GPIO pins are open drain, so the pins always remain outputs.
132   We rely on the i2c-algo-bit routines to set the pins high before
133   reading the input from other chips. */
134
135static int bit_vooi2c_getscl(void *data)
136{
137        return (0 != (readlong() & I2C_SCL_IN));
138}
139
140static int bit_vooi2c_getsda(void *data)
141{
142        return (0 != (readlong() & I2C_SDA_IN));
143}
144
145static void bit_vooddc_setscl(void *data, int val)
146{
147        unsigned int r;
148        r = readlong();
149        if(val)
150                r |= DDC_SCL_OUT;
151        else
152                r &= ~DDC_SCL_OUT;
153        outlong(r);
154}
155
156static void bit_vooddc_setsda(void *data, int val)
157{
158        unsigned int r;
159        r = readlong();
160        if(val)
161                r |= DDC_SDA_OUT;
162        else
163                r &= ~DDC_SDA_OUT;
164        outlong(r);
165}
166
167static int bit_vooddc_getscl(void *data)
168{
169        return (0 != (readlong() & DDC_SCL_IN));
170}
171
172static int bit_vooddc_getsda(void *data)
173{
174        return (0 != (readlong() & DDC_SDA_IN));
175}
176
177static struct i2c_algo_bit_data voo_i2c_bit_data = {
178        NULL,
179        bit_vooi2c_setsda,
180        bit_vooi2c_setscl,
181        bit_vooi2c_getsda,
182        bit_vooi2c_getscl,
183        CYCLE_DELAY, CYCLE_DELAY, TIMEOUT
184};
185
186static struct i2c_adapter voodoo3_i2c_adapter = {
187        "I2C Voodoo3/Banshee adapter",
188        I2C_HW_B_VOO,
189        NULL,
190        &voo_i2c_bit_data,
191        voodoo3_inc,
192        voodoo3_dec,
193        NULL,
194        NULL,
195};
196
197static struct i2c_algo_bit_data voo_ddc_bit_data = {
198        NULL,
199        bit_vooddc_setsda,
200        bit_vooddc_setscl,
201        bit_vooddc_getsda,
202        bit_vooddc_getscl,
203        CYCLE_DELAY, CYCLE_DELAY, TIMEOUT
204};
205
206static struct i2c_adapter voodoo3_ddc_adapter = {
207        "DDC Voodoo3/Banshee adapter",
208        I2C_HW_B_VOO,
209        NULL,
210        &voo_ddc_bit_data,
211        voodoo3_inc,
212        voodoo3_dec,
213        NULL,
214        NULL,
215};
216
217/* Configures the chip */
218
219void config_v3(struct pci_dev *dev)
220{
221        unsigned int cadr;
222
223        /* map Voodoo3 memory */
224#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
225        cadr = dev->resource[0].start;
226#else
227        cadr = dev->base_address[0];
228#endif
229        cadr &= PCI_BASE_ADDRESS_MEM_MASK;
230        mem = ioremap_nocache(cadr, 0x1000);
231
232        *((unsigned int *) (mem + REG2)) = 0x8160;
233        *((unsigned int *) (mem + REG)) = 0xcffc0020;
234        printk("i2c-voodoo3: Using Banshee/Voodoo3 at 0x%p\n", mem);
235}
236
237/* Detect whether a Voodoo3 or a Banshee can be found,
238   and initialize it. */
239static int voodoo3_setup(void)
240{
241        struct pci_dev *dev;
242        int v3_num;
243
244        v3_num = 0;
245
246        dev = NULL;
247        do {
248                if ((dev = pci_find_device(PCI_VENDOR_ID_3DFX,
249                                           PCI_DEVICE_ID_3DFX_VOODOO3,
250                                           dev))) {
251                        if (!v3_num)
252                                config_v3(dev);
253                        v3_num++;
254                }
255        } while (dev);
256
257        dev = NULL;
258        do {
259                if ((dev = pci_find_device(PCI_VENDOR_ID_3DFX,
260                                           PCI_DEVICE_ID_3DFX_BANSHEE,
261                                           dev))) {
262                        if (!v3_num)
263                                config_v3(dev);
264                        v3_num++;
265                }
266        } while (dev);
267
268        if (v3_num > 0) {
269                printk("i2c-voodoo3: %d Banshee/Voodoo3 found.\n", v3_num);
270                if (v3_num > 1)
271                        printk("i2c-voodoo3: warning: only 1 supported.\n");
272                return 0;
273        } else {
274                printk("i2c-voodoo3: No Voodoo3 found.\n");
275                return -ENODEV;
276        }
277}
278
279void voodoo3_inc(struct i2c_adapter *adapter)
280{
281        MOD_INC_USE_COUNT;
282}
283
284void voodoo3_dec(struct i2c_adapter *adapter)
285{
286        MOD_DEC_USE_COUNT;
287}
288
289int __init i2c_voodoo3_init(void)
290{
291        int res;
292        printk("i2c-voodoo3.o version %s (%s)\n", LM_VERSION, LM_DATE);
293        voodoo3_initialized = 0;
294        if ((res = voodoo3_setup())) {
295                printk
296                    ("i2c-voodoo3.o: Voodoo3 not detected, module not inserted.\n");
297                voodoo3_cleanup();
298                return res;
299        }
300        if ((res = i2c_bit_add_bus(&voodoo3_i2c_adapter))) {
301                printk("i2c-voodoo3.o: I2C adapter registration failed\n");
302        } else {
303                printk("i2c-voodoo3.o: I2C bus initialized\n");
304                voodoo3_initialized |= INIT2;
305        }
306        if ((res = i2c_bit_add_bus(&voodoo3_ddc_adapter))) {
307                printk("i2c-voodoo3.o: DDC adapter registration failed\n");
308        } else {
309                printk("i2c-voodoo3.o: DDC bus initialized\n");
310                voodoo3_initialized |= INIT3;
311        }
312        if(!(voodoo3_initialized & (INIT2 | INIT3))) {
313                printk("i2c-voodoo3.o: Both registrations failed, module not inserted\n");
314                voodoo3_cleanup();
315                return res;
316        }
317        return 0;
318}
319
320int __init voodoo3_cleanup(void)
321{
322        int res;
323
324        iounmap(mem);
325        if (voodoo3_initialized & INIT3) {
326                if ((res = i2c_bit_del_bus(&voodoo3_ddc_adapter))) {
327                        printk
328                            ("i2c-voodoo3.o: i2c_bit_del_bus failed, module not removed\n");
329                        return res;
330                }
331        }
332        if (voodoo3_initialized & INIT2) {
333                if ((res = i2c_bit_del_bus(&voodoo3_i2c_adapter))) {
334                        printk
335                            ("i2c-voodoo3.o: i2c_bit_del_bus failed, module not removed\n");
336                        return res;
337                }
338        }
339        return 0;
340}
341
342EXPORT_NO_SYMBOLS;
343
344#ifdef MODULE
345
346MODULE_AUTHOR
347    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
348MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver");
349
350
351int init_module(void)
352{
353        return i2c_voodoo3_init();
354}
355
356int cleanup_module(void)
357{
358        return voodoo3_cleanup();
359}
360
361#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.