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
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 .owner = THIS_MODULE,
237 .name = "i810_smbus",
238 .id_table = i810_ids,
240 .remove = __devexit_p(i810_remove),
243 static int __init i2c_i810_init(void)
245 return pci_register_driver(&i810_driver);
248 static void __exit i2c_i810_exit(void)
250 pci_unregister_driver(&i810_driver);
253 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
254 "Philip Edelbrock <phil@netroedge.com>, "
255 "Ralph Metzler <rjkm@thp.uni-koeln.de>, "
256 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
257 MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
258 MODULE_LICENSE("GPL");
260 module_init(i2c_i810_init);
261 module_exit(i2c_i810_exit);