aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-savage4.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/i2c/busses/i2c-savage4.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/i2c/busses/i2c-savage4.c')
-rw-r--r--drivers/i2c/busses/i2c-savage4.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
new file mode 100644
index 000000000000..092d0323c6c6
--- /dev/null
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -0,0 +1,205 @@
1/*
2 i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
3 monitoring
4 Copyright (C) 1998-2003 The LM Sensors Team
5 Alexander Wold <awold@bigfoot.com>
6 Mark D. Studebaker <mdsxyz123@yahoo.com>
7
8 Based on i2c-voodoo3.c.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25/* This interfaces to the I2C bus of the Savage4 to gain access to
26 the BT869 and possibly other I2C devices. The DDC bus is not
27 yet supported because its register is not memory-mapped.
28 However we leave the DDC code here, commented out, to make
29 it easier to add later.
30*/
31
32#include <linux/config.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/pci.h>
37#include <linux/i2c.h>
38#include <linux/i2c-algo-bit.h>
39#include <asm/io.h>
40
41/* 3DFX defines */
42#define PCI_CHIP_SAVAGE3D 0x8A20
43#define PCI_CHIP_SAVAGE3D_MV 0x8A21
44#define PCI_CHIP_SAVAGE4 0x8A22
45#define PCI_CHIP_SAVAGE2000 0x9102
46#define PCI_CHIP_PROSAVAGE_PM 0x8A25
47#define PCI_CHIP_PROSAVAGE_KM 0x8A26
48#define PCI_CHIP_SAVAGE_MX_MV 0x8c10
49#define PCI_CHIP_SAVAGE_MX 0x8c11
50#define PCI_CHIP_SAVAGE_IX_MV 0x8c12
51#define PCI_CHIP_SAVAGE_IX 0x8c13
52
53#define REG 0xff20 /* Serial Port 1 Register */
54
55/* bit locations in the register */
56#define DDC_ENAB 0x00040000
57#define DDC_SCL_OUT 0x00080000
58#define DDC_SDA_OUT 0x00100000
59#define DDC_SCL_IN 0x00200000
60#define DDC_SDA_IN 0x00400000
61#define I2C_ENAB 0x00000020
62#define I2C_SCL_OUT 0x00000001
63#define I2C_SDA_OUT 0x00000002
64#define I2C_SCL_IN 0x00000008
65#define I2C_SDA_IN 0x00000010
66
67/* initialization states */
68#define INIT2 0x20
69#define INIT3 0x04
70
71/* delays */
72#define CYCLE_DELAY 10
73#define TIMEOUT (HZ / 2)
74
75
76static void __iomem *ioaddr;
77
78/* The sav GPIO registers don't have individual masks for each bit
79 so we always have to read before writing. */
80
81static void bit_savi2c_setscl(void *data, int val)
82{
83 unsigned int r;
84 r = readl(ioaddr + REG);
85 if(val)
86 r |= I2C_SCL_OUT;
87 else
88 r &= ~I2C_SCL_OUT;
89 writel(r, ioaddr + REG);
90 readl(ioaddr + REG); /* flush posted write */
91}
92
93static void bit_savi2c_setsda(void *data, int val)
94{
95 unsigned int r;
96 r = readl(ioaddr + REG);
97 if(val)
98 r |= I2C_SDA_OUT;
99 else
100 r &= ~I2C_SDA_OUT;
101 writel(r, ioaddr + REG);
102 readl(ioaddr + REG); /* flush posted write */
103}
104
105/* The GPIO pins are open drain, so the pins always remain outputs.
106 We rely on the i2c-algo-bit routines to set the pins high before
107 reading the input from other chips. */
108
109static int bit_savi2c_getscl(void *data)
110{
111 return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
112}
113
114static int bit_savi2c_getsda(void *data)
115{
116 return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
117}
118
119/* Configures the chip */
120
121static int config_s4(struct pci_dev *dev)
122{
123 unsigned long cadr;
124
125 /* map memory */
126 cadr = dev->resource[0].start;
127 cadr &= PCI_BASE_ADDRESS_MEM_MASK;
128 ioaddr = ioremap_nocache(cadr, 0x0080000);
129 if (ioaddr) {
130 /* writel(0x8160, ioaddr + REG2); */
131 writel(0x00000020, ioaddr + REG);
132 dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr);
133 return 0;
134 }
135 return -ENODEV;
136}
137
138static struct i2c_algo_bit_data sav_i2c_bit_data = {
139 .setsda = bit_savi2c_setsda,
140 .setscl = bit_savi2c_setscl,
141 .getsda = bit_savi2c_getsda,
142 .getscl = bit_savi2c_getscl,
143 .udelay = CYCLE_DELAY,
144 .mdelay = CYCLE_DELAY,
145 .timeout = TIMEOUT
146};
147
148static struct i2c_adapter savage4_i2c_adapter = {
149 .owner = THIS_MODULE,
150 .name = "I2C Savage4 adapter",
151 .algo_data = &sav_i2c_bit_data,
152};
153
154static struct pci_device_id savage4_ids[] __devinitdata = {
155 { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) },
156 { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) },
157 { 0, }
158};
159
160MODULE_DEVICE_TABLE (pci, savage4_ids);
161
162static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
163{
164 int retval;
165
166 retval = config_s4(dev);
167 if (retval)
168 return retval;
169
170 /* set up the sysfs linkage to our parent device */
171 savage4_i2c_adapter.dev.parent = &dev->dev;
172
173 return i2c_bit_add_bus(&savage4_i2c_adapter);
174}
175
176static void __devexit savage4_remove(struct pci_dev *dev)
177{
178 i2c_bit_del_bus(&savage4_i2c_adapter);
179 iounmap(ioaddr);
180}
181
182static struct pci_driver savage4_driver = {
183 .name = "savage4_smbus",
184 .id_table = savage4_ids,
185 .probe = savage4_probe,
186 .remove = __devexit_p(savage4_remove),
187};
188
189static int __init i2c_savage4_init(void)
190{
191 return pci_register_driver(&savage4_driver);
192}
193
194static void __exit i2c_savage4_exit(void)
195{
196 pci_unregister_driver(&savage4_driver);
197}
198
199MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> "
200 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
201MODULE_DESCRIPTION("Savage4 I2C/SMBus driver");
202MODULE_LICENSE("GPL");
203
204module_init(i2c_savage4_init);
205module_exit(i2c_savage4_exit);