root/lm-sensors/trunk/kernel/busses/i2c-i810.c @ 1281

Revision 1281, 8.3 KB (checked in by mds, 11 years ago)

add support for 810E (PCI 0x7125)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware
3              monitoring
4    Copyright (c) 1998, 1999, 2000  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 I810/I815 to provide access to
28   the DDC Bus and the I2C Bus.
29
30   SUPPORTED DEVICES    PCI ID
31   i810AA               7121           
32   i810AB               7123           
33   i810E                7125           
34   i815                 1132           
35*/
36
37
38#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/pci.h>
41#include <asm/io.h>
42#include <linux/i2c.h>
43#include <linux/i2c-algo-bit.h>
44#include "version.h"
45#include <linux/init.h>
46
47#ifdef MODULE_LICENSE
48MODULE_LICENSE("GPL");
49#endif
50
51/* PCI defines */
52#ifndef PCI_DEVICE_ID_INTEL_82810_IG1
53#define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121
54#endif
55#ifndef PCI_DEVICE_ID_INTEL_82810_IG3
56#define PCI_DEVICE_ID_INTEL_82810_IG3 0x7123
57#endif
58#ifndef PCI_DEVICE_ID_INTEL_82815_2
59#define PCI_DEVICE_ID_INTEL_82815_2   0x1132
60#endif
61
62static int i810_supported[] = {PCI_DEVICE_ID_INTEL_82810_IG1,
63                               PCI_DEVICE_ID_INTEL_82810_IG3,
64                               0x7125,
65                               PCI_DEVICE_ID_INTEL_82815_2,
66                               0 };
67
68/* GPIO register locations */
69#define I810_IOCONTROL_OFFSET 0x5000
70#define I810_HVSYNC     0x00    /* not used */
71#define I810_GPIOA      0x10
72#define I810_GPIOB      0x14
73
74/* bit locations in the registers */
75#define SCL_DIR_MASK    0x0001
76#define SCL_DIR         0x0002
77#define SCL_VAL_MASK    0x0004
78#define SCL_VAL_OUT     0x0008
79#define SCL_VAL_IN      0x0010
80#define SDA_DIR_MASK    0x0100
81#define SDA_DIR         0x0200
82#define SDA_VAL_MASK    0x0400
83#define SDA_VAL_OUT     0x0800
84#define SDA_VAL_IN      0x1000
85
86/* initialization states */
87#define INIT1   0x1
88#define INIT2   0x2
89#define INIT3   0x4
90
91/* delays */
92#define CYCLE_DELAY             10
93#define TIMEOUT                 50
94
95#ifdef MODULE
96static
97#else
98extern
99#endif
100int __init i2c_i810_init(void);
101static int __init i810i2c_cleanup(void);
102static int i810i2c_setup(void);
103static void config_i810(struct pci_dev *dev);
104static void i810_inc(struct i2c_adapter *adapter);
105static void i810_dec(struct i2c_adapter *adapter);
106
107#ifdef MODULE
108extern int init_module(void);
109extern int cleanup_module(void);
110#endif                          /* MODULE */
111
112static int __initdata i810i2c_initialized;
113static unsigned char *mem;
114
115static inline void outlong(unsigned int dat, int off)
116{
117        *((unsigned int *) (mem + off)) = dat;
118}
119
120static inline unsigned int readlong(int off)
121{
122        return *((unsigned int *) (mem + off));
123}
124
125/* The i810 GPIO registers have individual masks for each bit
126   so we never have to read before writing. Nice. */
127
128static void bit_i810i2c_setscl(void *data, int val)
129{
130        outlong((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
131             I810_GPIOB);
132}
133
134static void bit_i810i2c_setsda(void *data, int val)
135{
136        outlong((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
137             I810_GPIOB);
138}
139
140/* The GPIO pins are open drain, so the pins always remain outputs.
141   We rely on the i2c-algo-bit routines to set the pins high before
142   reading the input from other chips. Following guidance in the 815
143   prog. ref. guide, we do a "dummy write" of 0 to the register before
144   reading which forces the input value to be latched. We presume this
145   applies to the 810 as well. This is necessary to get
146   i2c_algo_bit bit_test=1 to pass. */
147
148static int bit_i810i2c_getscl(void *data)
149{
150        outlong(0, I810_GPIOB);
151        return (0 != (readlong(I810_GPIOB) & SCL_VAL_IN));
152}
153
154static int bit_i810i2c_getsda(void *data)
155{
156        outlong(0, I810_GPIOB);
157        return (0 != (readlong(I810_GPIOB) & SDA_VAL_IN));
158}
159
160static void bit_i810ddc_setscl(void *data, int val)
161{
162        outlong((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
163             I810_GPIOA);
164}
165
166static void bit_i810ddc_setsda(void *data, int val)
167{
168        outlong((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
169             I810_GPIOA);
170}
171
172static int bit_i810ddc_getscl(void *data)
173{
174        outlong(0, I810_GPIOA);
175        return (0 != (readlong(I810_GPIOA) & SCL_VAL_IN));
176}
177
178static int bit_i810ddc_getsda(void *data)
179{
180        outlong(0, I810_GPIOA);
181        return (0 != (readlong(I810_GPIOA) & SDA_VAL_IN));
182}
183
184static struct i2c_algo_bit_data i810_i2c_bit_data = {
185        NULL,
186        bit_i810i2c_setsda,
187        bit_i810i2c_setscl,
188        bit_i810i2c_getsda,
189        bit_i810i2c_getscl,
190        CYCLE_DELAY, CYCLE_DELAY, TIMEOUT
191};
192
193static struct i2c_adapter i810_i2c_adapter = {
194        "I810/I815 I2C Adapter",
195        I2C_HW_B_I810,
196        NULL,
197        &i810_i2c_bit_data,
198        i810_inc,
199        i810_dec,
200        NULL,
201        NULL,
202};
203
204static struct i2c_algo_bit_data i810_ddc_bit_data = {
205        NULL,
206        bit_i810ddc_setsda,
207        bit_i810ddc_setscl,
208        bit_i810ddc_getsda,
209        bit_i810ddc_getscl,
210        CYCLE_DELAY, CYCLE_DELAY, TIMEOUT
211};
212
213static struct i2c_adapter i810_ddc_adapter = {
214        "I810/I815 DDC Adapter",
215        I2C_HW_B_I810,
216        NULL,
217        &i810_ddc_bit_data,
218        i810_inc,
219        i810_dec,
220        NULL,
221        NULL,
222};
223
224
225/* Configures the chip */
226void config_i810(struct pci_dev *dev)
227{
228        unsigned long cadr;
229
230        /* map I810 memory */
231#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
232        cadr = dev->resource[1].start;
233#else
234        cadr = dev->base_address[1];
235#endif
236        cadr += I810_IOCONTROL_OFFSET;
237        cadr &= PCI_BASE_ADDRESS_MEM_MASK;
238        mem = ioremap_nocache(cadr, 0x1000);
239        bit_i810i2c_setscl(NULL, 1);
240        bit_i810i2c_setsda(NULL, 1);
241        bit_i810ddc_setscl(NULL, 1);
242        bit_i810ddc_setsda(NULL, 1);
243}
244
245/* Detect whether a supported device can be found,
246   and initialize it */
247static int i810i2c_setup(void)
248{
249        struct pci_dev *dev = NULL;
250        int *num = i810_supported;
251
252        do {
253                if ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
254                                           *num++, dev))) {
255                        config_i810(dev);
256                        printk("i2c-i810.o: i810/i815 found.\n");
257                        return 0;
258                }
259        } while (*num != 0);
260
261        return -ENODEV;
262}
263
264
265void i810_inc(struct i2c_adapter *adapter)
266{
267        MOD_INC_USE_COUNT;
268}
269
270void i810_dec(struct i2c_adapter *adapter)
271{
272        MOD_DEC_USE_COUNT;
273}
274
275int __init i2c_i810_init(void)
276{
277        int res;
278        printk("i2c-i810.o version %s (%s)\n", LM_VERSION, LM_DATE);
279
280        i810i2c_initialized = 0;
281        if ((res = i810i2c_setup())) {
282                printk
283                    ("i2c-i810.o: i810/i815 not detected, module not inserted.\n");
284                i810i2c_cleanup();
285                return res;
286        }
287        if ((res = i2c_bit_add_bus(&i810_i2c_adapter))) {
288                printk("i2c-i810.o: I2C adapter registration failed\n");
289        } else {
290                printk("i2c-i810.o: I810/I815 I2C bus initialized\n");
291                i810i2c_initialized |= INIT2;
292        }
293        if ((res = i2c_bit_add_bus(&i810_ddc_adapter))) {
294                printk("i2c-i810.o: DDC adapter registration failed\n");
295        } else {
296                printk("i2c-i810.o: I810/I815 DDC bus initialized\n");
297                i810i2c_initialized |= INIT3;
298        }
299        if(!(i810i2c_initialized & (INIT2 | INIT3))) {
300                printk("i2c-i810.o: Both registrations failed, module not inserted\n");
301                i810i2c_cleanup();
302                return res;
303        }
304        return 0;
305}
306
307int __init i810i2c_cleanup(void)
308{
309        int res;
310
311        iounmap(mem);
312        if (i810i2c_initialized & INIT3) {
313                if ((res = i2c_bit_del_bus(&i810_ddc_adapter))) {
314                        printk
315                            ("i2c-i810.o: i2c_del_adapter failed, module not removed\n");
316                        return res;
317                }
318        }
319        if (i810i2c_initialized & INIT2) {
320                if ((res = i2c_bit_del_bus(&i810_i2c_adapter))) {
321                        printk
322                            ("i2c-i810.o: i2c_del_adapter failed, module not removed\n");
323                        return res;
324                }
325        }
326        i810i2c_initialized = 0;
327        return 0;
328}
329
330EXPORT_NO_SYMBOLS;
331
332#ifdef MODULE
333
334MODULE_AUTHOR
335    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
336MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
337
338
339int init_module(void)
340{
341        return i2c_i810_init();
342}
343
344int cleanup_module(void)
345{
346        return i810i2c_cleanup();
347}
348
349#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.