Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
420 giacomo 1
/*
2
    i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
3
              monitoring
4
    Copyright (c) 1998, 1999  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 I2C bus of the Savage4 to gain access to
28
   the BT869 and possibly other I2C devices. The DDC bus is not
29
   yet supported because its register is not memory-mapped.
30
   However we leave the DDC code here, commented out, to make
31
   it easier to add later.
32
*/
33
 
34
#include <linux/kernel.h>
35
#include <linux/module.h>
36
#include <linux/init.h>
37
#include <linux/pci.h>
38
#include <linux/i2c.h>
39
#include <linux/i2c-algo-bit.h>
40
#include <asm/io.h>
41
 
42
/* 3DFX defines */
43
#define PCI_CHIP_SAVAGE3D       0x8A20
44
#define PCI_CHIP_SAVAGE3D_MV    0x8A21
45
#define PCI_CHIP_SAVAGE4        0x8A22
46
#define PCI_CHIP_SAVAGE2000     0x9102
47
#define PCI_CHIP_PROSAVAGE_PM   0x8A25
48
#define PCI_CHIP_PROSAVAGE_KM   0x8A26
49
#define PCI_CHIP_SAVAGE_MX_MV   0x8c10
50
#define PCI_CHIP_SAVAGE_MX      0x8c11
51
#define PCI_CHIP_SAVAGE_IX_MV   0x8c12
52
#define PCI_CHIP_SAVAGE_IX      0x8c13
53
 
54
#define REG                     0xff20  /* Serial Port 1 Register */
55
 
56
/* bit locations in the register */
57
#define DDC_ENAB                0x00040000
58
#define DDC_SCL_OUT             0x00080000
59
#define DDC_SDA_OUT             0x00100000
60
#define DDC_SCL_IN              0x00200000
61
#define DDC_SDA_IN              0x00400000
62
#define I2C_ENAB                0x00000020
63
#define I2C_SCL_OUT             0x00000001
64
#define I2C_SDA_OUT             0x00000002
65
#define I2C_SCL_IN              0x00000008
66
#define I2C_SDA_IN              0x00000010
67
 
68
/* initialization states */
69
#define INIT2                   0x20
70
#define INIT3                   0x04
71
 
72
/* delays */
73
#define CYCLE_DELAY             10
74
#define TIMEOUT                 (HZ / 2)
75
 
76
 
77
static void *ioaddr;
78
 
79
/* The sav GPIO registers don't have individual masks for each bit
80
   so we always have to read before writing. */
81
 
82
static void bit_savi2c_setscl(void *data, int val)
83
{
84
        unsigned int r;
85
        r = readl(ioaddr + REG);
86
        if(val)
87
                r |= I2C_SCL_OUT;
88
        else
89
                r &= ~I2C_SCL_OUT;
90
        writel(r, ioaddr + REG);
91
        readl(ioaddr + REG);    /* flush posted write */
92
}
93
 
94
static void bit_savi2c_setsda(void *data, int val)
95
{
96
        unsigned int r;
97
        r = readl(ioaddr + REG);
98
        if(val)
99
                r |= I2C_SDA_OUT;
100
        else
101
                r &= ~I2C_SDA_OUT;
102
        writel(r, ioaddr + REG);
103
        readl(ioaddr + REG);    /* flush posted write */
104
}
105
 
106
/* The GPIO pins are open drain, so the pins always remain outputs.
107
   We rely on the i2c-algo-bit routines to set the pins high before
108
   reading the input from other chips. */
109
 
110
static int bit_savi2c_getscl(void *data)
111
{
112
        return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
113
}
114
 
115
static int bit_savi2c_getsda(void *data)
116
{
117
        return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
118
}
119
 
120
/* Configures the chip */
121
 
122
static int config_s4(struct pci_dev *dev)
123
{
124
        unsigned int cadr;
125
 
126
        /* map memory */
127
        cadr = dev->resource[0].start;
128
        cadr &= PCI_BASE_ADDRESS_MEM_MASK;
129
        ioaddr = ioremap_nocache(cadr, 0x0080000);
130
        if (ioaddr) {
131
                /* writel(0x8160, ioaddr + REG2); */
132
                writel(0x00000020, ioaddr + REG);
133
                dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr);
134
                return 0;
135
        }
136
        return -ENODEV;
137
}
138
 
139
static struct i2c_algo_bit_data sav_i2c_bit_data = {
140
        .setsda         = bit_savi2c_setsda,
141
        .setscl         = bit_savi2c_setscl,
142
        .getsda         = bit_savi2c_getsda,
143
        .getscl         = bit_savi2c_getscl,
144
        .udelay         = CYCLE_DELAY,
145
        .mdelay         = CYCLE_DELAY,
146
        .timeout        = TIMEOUT
147
};
148
 
149
static struct i2c_adapter savage4_i2c_adapter = {
150
        .owner          = THIS_MODULE,
151
        .name           = "I2C Savage4 adapter",
152
        .algo_data      = &sav_i2c_bit_data,
153
};
154
 
155
static struct pci_device_id savage4_ids[] __devinitdata = {
156
        { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) },
157
        { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) },
158
        { 0, }
159
};
160
 
161
static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
162
{
163
        int retval;
164
 
165
        retval = config_s4(dev);
166
        if (retval)
167
                return retval;
168
 
169
        /* set up the sysfs linkage to our parent device */
170
        savage4_i2c_adapter.dev.parent = &dev->dev;
171
 
172
        return i2c_bit_add_bus(&savage4_i2c_adapter);
173
}
174
 
175
static void __devexit savage4_remove(struct pci_dev *dev)
176
{
177
        i2c_bit_del_bus(&savage4_i2c_adapter);
178
        iounmap(ioaddr);
179
}
180
 
181
static struct pci_driver savage4_driver = {
182
        .name           = "savage4 smbus",
183
        .id_table       = savage4_ids,
184
        .probe          = savage4_probe,
185
        .remove         = __devexit_p(savage4_remove),
186
};
187
 
188
static int __init i2c_savage4_init(void)
189
{
190
        return pci_module_init(&savage4_driver);
191
}
192
 
193
static void __exit i2c_savage4_exit(void)
194
{
195
        pci_unregister_driver(&savage4_driver);
196
}
197
 
198
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
199
                "Philip Edelbrock <phil@netroedge.com>, "
200
                "Ralph Metzler <rjkm@thp.uni-koeln.de>, "
201
                "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
202
MODULE_DESCRIPTION("Savage4 I2C/SMBus driver");
203
MODULE_LICENSE("GPL");
204
 
205
module_init(i2c_savage4_init);
206
module_exit(i2c_savage4_exit);