PageRenderTime 22ms CodeModel.GetById 10ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/i2c/busses/i2c-i810.c

https://bitbucket.org/evzijst/gittest
C | 260 lines | 174 code | 34 blank | 52 comment | 8 complexity | 58c2dc9c8e1b40b5f60f6a28e08e7da5 MD5 | raw file
  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#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>
 44#include <asm/io.h>
 45
 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
 51
 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
 63
 64/* initialization states */
 65#define INIT1			0x1
 66#define INIT2			0x2
 67#define INIT3			0x4
 68
 69/* delays */
 70#define CYCLE_DELAY		10
 71#define TIMEOUT			(HZ / 2)
 72
 73static void __iomem *ioaddr;
 74
 75/* The i810 GPIO registers have individual masks for each bit
 76   so we never have to read before writing. Nice. */
 77
 78static void bit_i810i2c_setscl(void *data, int val)
 79{
 80	writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
 81	     ioaddr + I810_GPIOB);
 82	readl(ioaddr + I810_GPIOB);	/* flush posted write */
 83}
 84
 85static void bit_i810i2c_setsda(void *data, int val)
 86{
 87 	writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
 88	     ioaddr + I810_GPIOB);
 89	readl(ioaddr + I810_GPIOB);	/* flush posted write */
 90}
 91
 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
 94   are set as inputs.
 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. */
101
102static int bit_i810i2c_getscl(void *data)
103{
104	writel(SCL_DIR_MASK, ioaddr + I810_GPIOB);
105	writel(0, ioaddr + I810_GPIOB);
106	return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN));
107}
108
109static int bit_i810i2c_getsda(void *data)
110{
111	writel(SDA_DIR_MASK, ioaddr + I810_GPIOB);
112	writel(0, ioaddr + I810_GPIOB);
113	return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN));
114}
115
116static void bit_i810ddc_setscl(void *data, int val)
117{
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 */
121}
122
123static void bit_i810ddc_setsda(void *data, int val)
124{
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 */
128}
129
130static int bit_i810ddc_getscl(void *data)
131{
132	writel(SCL_DIR_MASK, ioaddr + I810_GPIOA);
133	writel(0, ioaddr + I810_GPIOA);
134	return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN));
135}
136
137static int bit_i810ddc_getsda(void *data)
138{
139	writel(SDA_DIR_MASK, ioaddr + I810_GPIOA);
140	writel(0, ioaddr + I810_GPIOA);
141	return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN));
142}
143
144static int config_i810(struct pci_dev *dev)
145{
146	unsigned long cadr;
147
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);
153	if (ioaddr) {
154		bit_i810i2c_setscl(NULL, 1);
155		bit_i810i2c_setsda(NULL, 1);
156		bit_i810ddc_setscl(NULL, 1);
157		bit_i810ddc_setsda(NULL, 1);
158		return 0;
159	}
160	return -ENODEV;
161}
162
163static 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,
170	.timeout	= TIMEOUT,
171};
172
173static struct i2c_adapter i810_i2c_adapter = {
174	.owner		= THIS_MODULE,
175	.name		= "I810/I815 I2C Adapter",
176	.algo_data	= &i810_i2c_bit_data,
177};
178
179static 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,
186	.timeout	= TIMEOUT,
187};
188
189static struct i2c_adapter i810_ddc_adapter = {
190	.owner		= THIS_MODULE,
191	.name		= "I810/I815 DDC Adapter",
192	.algo_data	= &i810_ddc_bit_data,
193};
194
195static 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) },
201	{ 0, },
202};
203
204MODULE_DEVICE_TABLE (pci, i810_ids);
205
206static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id)
207{
208	int retval;
209
210	retval = config_i810(dev);
211	if (retval)
212		return retval;
213	dev_info(&dev->dev, "i810/i815 i2c device found.\n");
214
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;
218
219	retval = i2c_bit_add_bus(&i810_i2c_adapter);
220	if (retval)
221		return retval;
222	retval = i2c_bit_add_bus(&i810_ddc_adapter);
223	if (retval)
224		i2c_bit_del_bus(&i810_i2c_adapter);
225	return retval;
226}
227
228static void __devexit i810_remove(struct pci_dev *dev)
229{
230	i2c_bit_del_bus(&i810_ddc_adapter);
231	i2c_bit_del_bus(&i810_i2c_adapter);
232	iounmap(ioaddr);
233}
234
235static struct pci_driver i810_driver = {
236	.name		= "i810_smbus",
237	.id_table	= i810_ids,
238	.probe		= i810_probe,
239	.remove		= __devexit_p(i810_remove),
240};
241
242static int __init i2c_i810_init(void)
243{
244	return pci_register_driver(&i810_driver);
245}
246
247static void __exit i2c_i810_exit(void)
248{
249	pci_unregister_driver(&i810_driver);
250}
251
252MODULE_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>");
256MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
257MODULE_LICENSE("GPL");
258
259module_init(i2c_i810_init);
260module_exit(i2c_i810_exit);