2 i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware
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>
9 Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
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.
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.
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.
27 This interfaces to the I810/I815 to provide access to
28 the DDC Bus and the I2C Bus.
30 SUPPORTED DEVICES PCI ID
37 #include <linux/config.h>
38 #include <linux/kernel.h>
39 #include <linux/module.h>
40 #include <linux/init.h>
41 #include <linux/pci.h>
42 #include <linux/i2c.h>
43 #include <linux/i2c-algo-bit.h>
46 /* GPIO register locations */
47 #define I810_IOCONTROL_OFFSET 0x5000
48 #define I810_HVSYNC 0x00 /* not used */
49 #define I810_GPIOA 0x10
50 #define I810_GPIOB 0x14
52 /* bit locations in the registers */
53 #define SCL_DIR_MASK 0x0001
54 #define SCL_DIR 0x0002
55 #define SCL_VAL_MASK 0x0004
56 #define SCL_VAL_OUT 0x0008
57 #define SCL_VAL_IN 0x0010
58 #define SDA_DIR_MASK 0x0100
59 #define SDA_DIR 0x0200
60 #define SDA_VAL_MASK 0x0400
61 #define SDA_VAL_OUT 0x0800
62 #define SDA_VAL_IN 0x1000
64 /* initialization states */
70 #define CYCLE_DELAY 10
71 #define TIMEOUT (HZ / 2)
73 static void __iomem
*ioaddr
;
75 /* The i810 GPIO registers have individual masks for each bit
76 so we never have to read before writing. Nice. */
78 static void bit_i810i2c_setscl(void *data
, int val
)
80 writel((val
? SCL_VAL_OUT
: 0) | SCL_DIR
| SCL_DIR_MASK
| SCL_VAL_MASK
,
82 readl(ioaddr
+ I810_GPIOB
); /* flush posted write */
85 static void bit_i810i2c_setsda(void *data
, int val
)
87 writel((val
? SDA_VAL_OUT
: 0) | SDA_DIR
| SDA_DIR_MASK
| SDA_VAL_MASK
,
89 readl(ioaddr
+ I810_GPIOB
); /* flush posted write */
92 /* The GPIO pins are open drain, so the pins could always remain outputs.
93 However, some chip versions don't latch the inputs unless they
95 We rely on the i2c-algo-bit routines to set the pins high before
96 reading the input from other chips. Following guidance in the 815
97 prog. ref. guide, we do a "dummy write" of 0 to the register before
98 reading which forces the input value to be latched. We presume this
99 applies to the 810 as well; shouldn't hurt anyway. This is necessary to get
100 i2c_algo_bit bit_test=1 to pass. */
102 static int bit_i810i2c_getscl(void *data
)
104 writel(SCL_DIR_MASK
, ioaddr
+ I810_GPIOB
);
105 writel(0, ioaddr
+ I810_GPIOB
);
106 return (0 != (readl(ioaddr
+ I810_GPIOB
) & SCL_VAL_IN
));
109 static int bit_i810i2c_getsda(void *data
)
111 writel(SDA_DIR_MASK
, ioaddr
+ I810_GPIOB
);
112 writel(0, ioaddr
+ I810_GPIOB
);
113 return (0 != (readl(ioaddr
+ I810_GPIOB
) & SDA_VAL_IN
));
116 static void bit_i810ddc_setscl(void *data
, int val
)
118 writel((val
? SCL_VAL_OUT
: 0) | SCL_DIR
| SCL_DIR_MASK
| SCL_VAL_MASK
,
119 ioaddr
+ I810_GPIOA
);
120 readl(ioaddr
+ I810_GPIOA
); /* flush posted write */
123 static void bit_i810ddc_setsda(void *data
, int val
)
125 writel((val
? SDA_VAL_OUT
: 0) | SDA_DIR
| SDA_DIR_MASK
| SDA_VAL_MASK
,
126 ioaddr
+ I810_GPIOA
);
127 readl(ioaddr
+ I810_GPIOA
); /* flush posted write */
130 static int bit_i810ddc_getscl(void *data
)
132 writel(SCL_DIR_MASK
, ioaddr
+ I810_GPIOA
);
133 writel(0, ioaddr
+ I810_GPIOA
);
134 return (0 != (readl(ioaddr
+ I810_GPIOA
) & SCL_VAL_IN
));
137 static int bit_i810ddc_getsda(void *data
)
139 writel(SDA_DIR_MASK
, ioaddr
+ I810_GPIOA
);
140 writel(0, ioaddr
+ I810_GPIOA
);
141 return (0 != (readl(ioaddr
+ I810_GPIOA
) & SDA_VAL_IN
));
144 static int config_i810(struct pci_dev
*dev
)
148 /* map I810 memory */
149 cadr
= dev
->resource
[1].start
;
150 cadr
+= I810_IOCONTROL_OFFSET
;
151 cadr
&= PCI_BASE_ADDRESS_MEM_MASK
;
152 ioaddr
= ioremap_nocache(cadr
, 0x1000);
154 bit_i810i2c_setscl(NULL
, 1);
155 bit_i810i2c_setsda(NULL
, 1);
156 bit_i810ddc_setscl(NULL
, 1);
157 bit_i810ddc_setsda(NULL
, 1);
163 static struct i2c_algo_bit_data i810_i2c_bit_data
= {
164 .setsda
= bit_i810i2c_setsda
,
165 .setscl
= bit_i810i2c_setscl
,
166 .getsda
= bit_i810i2c_getsda
,
167 .getscl
= bit_i810i2c_getscl
,
168 .udelay
= CYCLE_DELAY
,
169 .mdelay
= CYCLE_DELAY
,
173 static struct i2c_adapter i810_i2c_adapter
= {
174 .owner
= THIS_MODULE
,
175 .name
= "I810/I815 I2C Adapter",
176 .algo_data
= &i810_i2c_bit_data
,
179 static struct i2c_algo_bit_data i810_ddc_bit_data
= {
180 .setsda
= bit_i810ddc_setsda
,
181 .setscl
= bit_i810ddc_setscl
,
182 .getsda
= bit_i810ddc_getsda
,
183 .getscl
= bit_i810ddc_getscl
,
184 .udelay
= CYCLE_DELAY
,
185 .mdelay
= CYCLE_DELAY
,
189 static struct i2c_adapter i810_ddc_adapter
= {
190 .owner
= THIS_MODULE
,
191 .name
= "I810/I815 DDC Adapter",
192 .algo_data
= &i810_ddc_bit_data
,
195 static struct pci_device_id i810_ids
[] __devinitdata
= {
196 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82810_IG1
) },
197 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82810_IG3
) },
198 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82810E_IG
) },
199 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82815_CGC
) },
200 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82845G_IG
) },
204 MODULE_DEVICE_TABLE (pci
, i810_ids
);
206 static int __devinit
i810_probe(struct pci_dev
*dev
, const struct pci_device_id
*id
)
210 retval
= config_i810(dev
);
213 dev_info(&dev
->dev
, "i810/i815 i2c device found.\n");
215 /* set up the sysfs linkage to our parent device */
216 i810_i2c_adapter
.dev
.parent
= &dev
->dev
;
217 i810_ddc_adapter
.dev
.parent
= &dev
->dev
;
219 retval
= i2c_bit_add_bus(&i810_i2c_adapter
);
222 retval
= i2c_bit_add_bus(&i810_ddc_adapter
);
224 i2c_bit_del_bus(&i810_i2c_adapter
);
228 static void __devexit
i810_remove(struct pci_dev
*dev
)
230 i2c_bit_del_bus(&i810_ddc_adapter
);
231 i2c_bit_del_bus(&i810_i2c_adapter
);
235 static struct pci_driver i810_driver
= {
236 .name
= "i810_smbus",
237 .id_table
= i810_ids
,
239 .remove
= __devexit_p(i810_remove
),
242 static int __init
i2c_i810_init(void)
244 return pci_register_driver(&i810_driver
);
247 static void __exit
i2c_i810_exit(void)
249 pci_unregister_driver(&i810_driver
);
252 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
253 "Philip Edelbrock <phil@netroedge.com>, "
254 "Ralph Metzler <rjkm@thp.uni-koeln.de>, "
255 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
256 MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
257 MODULE_LICENSE("GPL");
259 module_init(i2c_i810_init
);
260 module_exit(i2c_i810_exit
);