PageRenderTime 33ms CodeModel.GetById 12ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/i2c/busses/i2c-prosavage.c

https://bitbucket.org/evzijst/gittest
C | 334 lines | 191 code | 48 blank | 95 comment | 19 complexity | 4037c27efcbac0d36f4fc8257f8c8108 MD5 | raw file
  1/*
  2 *    kernel/busses/i2c-prosavage.c
  3 *
  4 *    i2c bus driver for S3/VIA 8365/8375 graphics processor.
  5 *    Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org>
  6 *    Based on code written by:
  7 *	Frodo Looijaard <frodol@dds.nl>,
  8 *	Philip Edelbrock <phil@netroedge.com>,
  9 *	Ralph Metzler <rjkm@thp.uni-koeln.de>, and
 10 *	Mark D. Studebaker <mdsxyz123@yahoo.com>
 11 *	Simon Vogl
 12 *	and others
 13 *
 14 *    Please read the lm_sensors documentation for details on use.
 15 *
 16 *    This program is free software; you can redistribute it and/or modify
 17 *    it under the terms of the GNU General Public License as published by
 18 *    the Free Software Foundation; either version 2 of the License, or
 19 *    (at your option) any later version.
 20 *
 21 *    This program is distributed in the hope that it will be useful,
 22 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 23 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 24 *    GNU General Public License for more details.
 25 *
 26 *    You should have received a copy of the GNU General Public License
 27 *    along with this program; if not, write to the Free Software
 28 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 29 *
 30 */
 31/*  18-05-2003 HVE - created
 32 *  14-06-2003 HVE - adapted for lm_sensors2
 33 *  17-06-2003 HVE - linux 2.5.xx compatible
 34 *  18-06-2003 HVE - codingstyle
 35 *  21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx
 36 *		     codingstyle, mmio enabled
 37 *
 38 *  This driver interfaces to the I2C bus of the VIA north bridge embedded
 39 *  ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips.
 40 *
 41 *  Graphics cores:
 42 *   S3/VIA KM266/VT8375 aka ProSavage8
 43 *   S3/VIA KM133/VT8365 aka Savage4
 44 *
 45 *  Two serial busses are implemented:
 46 *   SERIAL1 - I2C serial communications interface
 47 *   SERIAL2 - DDC2 monitor communications interface
 48 *
 49 *  Tested on a FX41 mainboard, see http://www.shuttle.com
 50 * 
 51 *
 52 *  TODO:
 53 *  - integration with prosavage framebuffer device
 54 *    (Additional documentation needed :(
 55 */
 56
 57#include <linux/config.h>
 58#include <linux/module.h>
 59#include <linux/init.h>
 60#include <linux/pci.h>
 61#include <linux/i2c.h>
 62#include <linux/i2c-algo-bit.h>
 63#include <asm/io.h>
 64
 65/*
 66 * driver configuration
 67 */
 68#define MAX_BUSSES	2
 69
 70struct s_i2c_bus {
 71	void __iomem *mmvga;
 72	int	i2c_reg;
 73	int	adap_ok;
 74	struct i2c_adapter		adap;
 75	struct i2c_algo_bit_data	algo;
 76};
 77
 78struct s_i2c_chip {
 79	void __iomem *mmio;
 80	struct s_i2c_bus	i2c_bus[MAX_BUSSES];
 81};
 82
 83
 84/*
 85 * i2c configuration
 86 */
 87#ifndef I2C_HW_B_S3VIA
 88#define I2C_HW_B_S3VIA	0x18	/* S3VIA ProSavage adapter		*/
 89#endif
 90
 91/* delays */
 92#define CYCLE_DELAY	10
 93#define TIMEOUT		(HZ / 2)
 94
 95
 96/* 
 97 * S3/VIA 8365/8375 registers
 98 */
 99#define VGA_CR_IX	0x3d4
100#define VGA_CR_DATA	0x3d5
101
102#define CR_SERIAL1	0xa0	/* I2C serial communications interface */
103#define MM_SERIAL1	0xff20
104#define CR_SERIAL2	0xb1	/* DDC2 monitor communications interface */
105
106/* based on vt8365 documentation */
107#define I2C_ENAB	0x10
108#define I2C_SCL_OUT	0x01
109#define I2C_SDA_OUT	0x02
110#define I2C_SCL_IN	0x04
111#define I2C_SDA_IN	0x08
112
113#define SET_CR_IX(p, val)	writeb((val), (p)->mmvga + VGA_CR_IX)
114#define SET_CR_DATA(p, val)	writeb((val), (p)->mmvga + VGA_CR_DATA)
115#define GET_CR_DATA(p)		readb((p)->mmvga + VGA_CR_DATA)
116
117
118/*
119 * Serial bus line handling
120 *
121 * serial communications register as parameter in private data
122 *
123 * TODO: locks with other code sections accessing video registers?
124 */
125static void bit_s3via_setscl(void *bus, int val)
126{
127	struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
128	unsigned int r;
129
130	SET_CR_IX(p, p->i2c_reg);
131	r = GET_CR_DATA(p);
132	r |= I2C_ENAB;
133	if (val) {
134		r |= I2C_SCL_OUT;
135	} else {
136		r &= ~I2C_SCL_OUT;
137	}
138	SET_CR_DATA(p, r);
139}
140
141static void bit_s3via_setsda(void *bus, int val)
142{
143	struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
144	unsigned int r;
145	
146	SET_CR_IX(p, p->i2c_reg);
147	r = GET_CR_DATA(p);
148	r |= I2C_ENAB;
149	if (val) {
150		r |= I2C_SDA_OUT;
151	} else {
152		r &= ~I2C_SDA_OUT;
153	}
154	SET_CR_DATA(p, r);
155}
156
157static int bit_s3via_getscl(void *bus)
158{
159	struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
160
161	SET_CR_IX(p, p->i2c_reg);
162	return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
163}
164
165static int bit_s3via_getsda(void *bus)
166{
167	struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
168
169	SET_CR_IX(p, p->i2c_reg);
170	return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
171}
172
173
174/*
175 * adapter initialisation
176 */
177static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
178{
179	int ret;
180	p->adap.owner	  = THIS_MODULE;
181	p->adap.id	  = I2C_HW_B_S3VIA;
182	p->adap.algo_data = &p->algo;
183	p->adap.dev.parent = &dev->dev;
184	p->algo.setsda	  = bit_s3via_setsda;
185	p->algo.setscl	  = bit_s3via_setscl;
186	p->algo.getsda	  = bit_s3via_getsda;
187	p->algo.getscl	  = bit_s3via_getscl;
188	p->algo.udelay	  = CYCLE_DELAY;
189	p->algo.mdelay	  = CYCLE_DELAY;
190	p->algo.timeout	  = TIMEOUT;
191	p->algo.data	  = p;
192	p->mmvga	  = mmvga;
193	p->i2c_reg	  = i2c_reg;
194    
195	ret = i2c_bit_add_bus(&p->adap);
196	if (ret) {
197		return ret;
198	}
199
200	p->adap_ok = 1;
201	return 0;
202}
203
204
205/*
206 * Cleanup stuff
207 */
208static void prosavage_remove(struct pci_dev *dev)
209{
210	struct s_i2c_chip *chip;
211	int i, ret;
212
213	chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
214
215	if (!chip) {
216		return;
217	}
218	for (i = MAX_BUSSES - 1; i >= 0; i--) {
219		if (chip->i2c_bus[i].adap_ok == 0)
220			continue;
221
222		ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
223	        if (ret) {
224			dev_err(&dev->dev, "%s not removed\n",
225				chip->i2c_bus[i].adap.name);
226		}
227	}
228	if (chip->mmio) {
229		iounmap(chip->mmio);
230	}
231	kfree(chip);
232}
233
234
235/*
236 * Detect chip and initialize it
237 */
238static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
239{
240	int ret;
241	unsigned long base, len;
242	struct s_i2c_chip *chip;
243	struct s_i2c_bus  *bus;
244
245        pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); 
246	chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
247	if (chip == NULL) {
248		return -ENOMEM;
249	}
250
251	memset(chip, 0, sizeof(struct s_i2c_chip));
252
253	base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
254	len  = dev->resource[0].end - base + 1;
255	chip->mmio = ioremap_nocache(base, len);
256
257	if (chip->mmio == NULL) {
258		dev_err(&dev->dev, "ioremap failed\n");
259		prosavage_remove(dev);
260		return -ENODEV;
261	}
262
263
264	/*
265	 * Chip initialisation
266	 */
267	/* Unlock Extended IO Space ??? */
268
269
270	/*
271	 * i2c bus registration
272	 */
273	bus = &chip->i2c_bus[0];
274	snprintf(bus->adap.name, sizeof(bus->adap.name),
275		"ProSavage I2C bus at %02x:%02x.%x",
276		dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
277	ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
278	if (ret) {
279		goto err_adap;
280	}
281	/*
282	 * ddc bus registration
283	 */
284	bus = &chip->i2c_bus[1];
285	snprintf(bus->adap.name, sizeof(bus->adap.name),
286		"ProSavage DDC bus at %02x:%02x.%x",
287		dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
288	ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
289	if (ret) {
290		goto err_adap;
291	}
292	return 0;
293err_adap:
294	dev_err(&dev->dev, "%s failed\n", bus->adap.name);
295	prosavage_remove(dev);
296	return ret;
297}
298
299
300/*
301 * Data for PCI driver interface
302 */
303static struct pci_device_id prosavage_pci_tbl[] = {
304	{ PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
305	{ PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
306	{ 0, },
307};
308
309MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
310
311static struct pci_driver prosavage_driver = {
312	.name		=	"prosavage_smbus",
313	.id_table	=	prosavage_pci_tbl,
314	.probe		=	prosavage_probe,
315	.remove		=	prosavage_remove,
316};
317
318static int __init i2c_prosavage_init(void)
319{
320	return pci_register_driver(&prosavage_driver);
321}
322
323static void __exit i2c_prosavage_exit(void)
324{
325	pci_unregister_driver(&prosavage_driver);
326}
327
328MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
329MODULE_AUTHOR("Henk Vergonet");
330MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
331MODULE_LICENSE("GPL");
332
333module_init (i2c_prosavage_init);
334module_exit (i2c_prosavage_exit);