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

Revision 1427, 8.5 KB (checked in by mds, 11 years ago)

flush PCI posted writes on algo-bit PCI drivers.

Also check return code on ioremap_nocache().

  • 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        readlong(I810_GPIOB);   /* flush posted write */
133}
134
135static void bit_i810i2c_setsda(void *data, int val)
136{
137        outlong((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
138             I810_GPIOB);
139        readlong(I810_GPIOB);   /* flush posted write */
140}
141
142/* The GPIO pins are open drain, so the pins always remain outputs.
143   We rely on the i2c-algo-bit routines to set the pins high before
144   reading the input from other chips. Following guidance in the 815
145   prog. ref. guide, we do a "dummy write" of 0 to the register before
146   reading which forces the input value to be latched. We presume this
147   applies to the 810 as well. This is necessary to get
148   i2c_algo_bit bit_test=1 to pass. */
149
150static int bit_i810i2c_getscl(void *data)
151{
152        outlong(0, I810_GPIOB);
153        return (0 != (readlong(I810_GPIOB) & SCL_VAL_IN));
154}
155
156static int bit_i810i2c_getsda(void *data)
157{
158        outlong(0, I810_GPIOB);
159        return (0 != (readlong(I810_GPIOB) & SDA_VAL_IN));
160}
161
162static void bit_i810ddc_setscl(void *data, int val)
163{
164        outlong((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
165             I810_GPIOA);
166        readlong(I810_GPIOA);   /* flush posted write */
167}
168
169static void bit_i810ddc_setsda(void *data, int val)
170{
171        outlong((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
172             I810_GPIOA);
173        readlong(I810_GPIOA);   /* flush posted write */
174}
175
176static int bit_i810ddc_getscl(void *data)
177{
178        outlong(0, I810_GPIOA);
179        return (0 != (readlong(I810_GPIOA) & SCL_VAL_IN));
180}
181
182static int bit_i810ddc_getsda(void *data)
183{
184        outlong(0, I810_GPIOA);
185        return (0 != (readlong(I810_GPIOA) & SDA_VAL_IN));
186}
187
188static struct i2c_algo_bit_data i810_i2c_bit_data = {
189        NULL,
190        bit_i810i2c_setsda,
191        bit_i810i2c_setscl,
192        bit_i810i2c_getsda,
193        bit_i810i2c_getscl,
194        CYCLE_DELAY, CYCLE_DELAY, TIMEOUT
195};
196
197static struct i2c_adapter i810_i2c_adapter = {
198        "I810/I815 I2C Adapter",
199        I2C_HW_B_I810,
200        NULL,
201        &i810_i2c_bit_data,
202        i810_inc,
203        i810_dec,
204        NULL,
205        NULL,
206};
207
208static struct i2c_algo_bit_data i810_ddc_bit_data = {
209        NULL,
210        bit_i810ddc_setsda,
211        bit_i810ddc_setscl,
212        bit_i810ddc_getsda,
213        bit_i810ddc_getscl,
214        CYCLE_DELAY, CYCLE_DELAY, TIMEOUT
215};
216
217static struct i2c_adapter i810_ddc_adapter = {
218        "I810/I815 DDC Adapter",
219        I2C_HW_B_I810,
220        NULL,
221        &i810_ddc_bit_data,
222        i810_inc,
223        i810_dec,
224        NULL,
225        NULL,
226};
227
228
229/* Configures the chip */
230void config_i810(struct pci_dev *dev)
231{
232        unsigned long cadr;
233
234        /* map I810 memory */
235#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
236        cadr = dev->resource[1].start;
237#else
238        cadr = dev->base_address[1];
239#endif
240        cadr += I810_IOCONTROL_OFFSET;
241        cadr &= PCI_BASE_ADDRESS_MEM_MASK;
242        mem = ioremap_nocache(cadr, 0x1000);
243        if(mem) {
244                bit_i810i2c_setscl(NULL, 1);
245                bit_i810i2c_setsda(NULL, 1);
246                bit_i810ddc_setscl(NULL, 1);
247                bit_i810ddc_setsda(NULL, 1);
248        }
249}
250
251/* Detect whether a supported device can be found,
252   and initialize it */
253static int i810i2c_setup(void)
254{
255        struct pci_dev *dev = NULL;
256        int *num = i810_supported;
257
258        do {
259                if ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
260                                           *num++, dev))) {
261                        config_i810(dev);
262                        if(!mem)
263                                return -ENOMEM;
264                        printk("i2c-i810.o: i810/i815 found.\n");
265                        return 0;
266                }
267        } while (*num != 0);
268
269        return -ENODEV;
270}
271
272
273void i810_inc(struct i2c_adapter *adapter)
274{
275        MOD_INC_USE_COUNT;
276}
277
278void i810_dec(struct i2c_adapter *adapter)
279{
280        MOD_DEC_USE_COUNT;
281}
282
283int __init i2c_i810_init(void)
284{
285        int res;
286        printk("i2c-i810.o version %s (%s)\n", LM_VERSION, LM_DATE);
287
288        i810i2c_initialized = 0;
289        if ((res = i810i2c_setup())) {
290                printk
291                    ("i2c-i810.o: i810/i815 not detected, module not inserted.\n");
292                i810i2c_cleanup();
293                return res;
294        }
295        if ((res = i2c_bit_add_bus(&i810_i2c_adapter))) {
296                printk("i2c-i810.o: I2C adapter registration failed\n");
297        } else {
298                printk("i2c-i810.o: I810/I815 I2C bus initialized\n");
299                i810i2c_initialized |= INIT2;
300        }
301        if ((res = i2c_bit_add_bus(&i810_ddc_adapter))) {
302                printk("i2c-i810.o: DDC adapter registration failed\n");
303        } else {
304                printk("i2c-i810.o: I810/I815 DDC bus initialized\n");
305                i810i2c_initialized |= INIT3;
306        }
307        if(!(i810i2c_initialized & (INIT2 | INIT3))) {
308                printk("i2c-i810.o: Both registrations failed, module not inserted\n");
309                i810i2c_cleanup();
310                return res;
311        }
312        return 0;
313}
314
315int __init i810i2c_cleanup(void)
316{
317        int res;
318
319        iounmap(mem);
320        if (i810i2c_initialized & INIT3) {
321                if ((res = i2c_bit_del_bus(&i810_ddc_adapter))) {
322                        printk
323                            ("i2c-i810.o: i2c_del_adapter failed, module not removed\n");
324                        return res;
325                }
326        }
327        if (i810i2c_initialized & INIT2) {
328                if ((res = i2c_bit_del_bus(&i810_i2c_adapter))) {
329                        printk
330                            ("i2c-i810.o: i2c_del_adapter failed, module not removed\n");
331                        return res;
332                }
333        }
334        i810i2c_initialized = 0;
335        return 0;
336}
337
338EXPORT_NO_SYMBOLS;
339
340#ifdef MODULE
341
342MODULE_AUTHOR
343    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
344MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
345
346
347int init_module(void)
348{
349        return i2c_i810_init();
350}
351
352int cleanup_module(void)
353{
354        return i810i2c_cleanup();
355}
356
357#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.