2 * kernel/busses/i2c-prosavage.c
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>
14 * Please read the lm_sensors documentation for details on use.
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.
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.
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.
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
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.
42 * S3/VIA KM266/VT8375 aka ProSavage8
43 * S3/VIA KM133/VT8365 aka Savage4
45 * Two serial busses are implemented:
46 * SERIAL1 - I2C serial communications interface
47 * SERIAL2 - DDC2 monitor communications interface
49 * Tested on a FX41 mainboard, see http://www.shuttle.com
53 * - integration with prosavage framebuffer device
54 * (Additional documentation needed :(
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>
66 * driver configuration
74 struct i2c_adapter adap
;
75 struct i2c_algo_bit_data algo
;
80 struct s_i2c_bus i2c_bus
[MAX_BUSSES
];
87 #ifndef I2C_HW_B_S3VIA
88 #define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */
92 #define CYCLE_DELAY 10
93 #define TIMEOUT (HZ / 2)
97 * S3/VIA 8365/8375 registers
99 #define VGA_CR_IX 0x3d4
100 #define VGA_CR_DATA 0x3d5
102 #define CR_SERIAL1 0xa0 /* I2C serial communications interface */
103 #define MM_SERIAL1 0xff20
104 #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
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
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)
119 * Serial bus line handling
121 * serial communications register as parameter in private data
123 * TODO: locks with other code sections accessing video registers?
125 static void bit_s3via_setscl(void *bus
, int val
)
127 struct s_i2c_bus
*p
= (struct s_i2c_bus
*)bus
;
130 SET_CR_IX(p
, p
->i2c_reg
);
141 static void bit_s3via_setsda(void *bus
, int val
)
143 struct s_i2c_bus
*p
= (struct s_i2c_bus
*)bus
;
146 SET_CR_IX(p
, p
->i2c_reg
);
157 static int bit_s3via_getscl(void *bus
)
159 struct s_i2c_bus
*p
= (struct s_i2c_bus
*)bus
;
161 SET_CR_IX(p
, p
->i2c_reg
);
162 return (0 != (GET_CR_DATA(p
) & I2C_SCL_IN
));
165 static int bit_s3via_getsda(void *bus
)
167 struct s_i2c_bus
*p
= (struct s_i2c_bus
*)bus
;
169 SET_CR_IX(p
, p
->i2c_reg
);
170 return (0 != (GET_CR_DATA(p
) & I2C_SDA_IN
));
175 * adapter initialisation
177 static int i2c_register_bus(struct pci_dev
*dev
, struct s_i2c_bus
*p
, void __iomem
*mmvga
, u32 i2c_reg
)
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
;
193 p
->i2c_reg
= i2c_reg
;
195 ret
= i2c_bit_add_bus(&p
->adap
);
208 static void prosavage_remove(struct pci_dev
*dev
)
210 struct s_i2c_chip
*chip
;
213 chip
= (struct s_i2c_chip
*)pci_get_drvdata(dev
);
218 for (i
= MAX_BUSSES
- 1; i
>= 0; i
--) {
219 if (chip
->i2c_bus
[i
].adap_ok
== 0)
222 ret
= i2c_bit_del_bus(&chip
->i2c_bus
[i
].adap
);
224 dev_err(&dev
->dev
, "%s not removed\n",
225 chip
->i2c_bus
[i
].adap
.name
);
236 * Detect chip and initialize it
238 static int __devinit
prosavage_probe(struct pci_dev
*dev
, const struct pci_device_id
*id
)
241 unsigned long base
, len
;
242 struct s_i2c_chip
*chip
;
243 struct s_i2c_bus
*bus
;
245 pci_set_drvdata(dev
, kmalloc(sizeof(struct s_i2c_chip
), GFP_KERNEL
));
246 chip
= (struct s_i2c_chip
*)pci_get_drvdata(dev
);
251 memset(chip
, 0, sizeof(struct s_i2c_chip
));
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
);
257 if (chip
->mmio
== NULL
) {
258 dev_err(&dev
->dev
, "ioremap failed\n");
259 prosavage_remove(dev
);
265 * Chip initialisation
267 /* Unlock Extended IO Space ??? */
271 * i2c bus registration
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
);
282 * ddc bus registration
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
);
294 dev_err(&dev
->dev
, "%s failed\n", bus
->adap
.name
);
295 prosavage_remove(dev
);
301 * Data for PCI driver interface
303 static 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
) },
309 MODULE_DEVICE_TABLE (pci
, prosavage_pci_tbl
);
311 static struct pci_driver prosavage_driver
= {
312 .name
= "prosavage_smbus",
313 .id_table
= prosavage_pci_tbl
,
314 .probe
= prosavage_probe
,
315 .remove
= prosavage_remove
,
318 static int __init
i2c_prosavage_init(void)
320 return pci_register_driver(&prosavage_driver
);
323 static void __exit
i2c_prosavage_exit(void)
325 pci_unregister_driver(&prosavage_driver
);
328 MODULE_DEVICE_TABLE(pci
, prosavage_pci_tbl
);
329 MODULE_AUTHOR("Henk Vergonet");
330 MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
331 MODULE_LICENSE("GPL");
333 module_init (i2c_prosavage_init
);
334 module_exit (i2c_prosavage_exit
);