root/lm-sensors/trunk/kernel/busses/i2c-nforce2.c @ 4321

Revision 4321, 12.1 KB (checked in by khali, 7 years ago)

i2c-nforce2: Drop unused reference to pci_dev. (2.6 backport)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    SMBus driver for nVidia nForce2 MCP
3
4    Copyright (c) 2003  Hans-Frieder Vogt <hfvogt@arcor.de>,
5    Based on
6    SMBus 2.0 driver for AMD-8111 IO-Hub
7    Copyright (c) 2002 Vojtech Pavlik
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/*
25    SUPPORTED DEVICES           PCI ID
26    nForce2 MCP                 0064
27    nForce2 Ultra 400 MCP       0084
28    nForce3 Pro150 MCP          00D4
29    nForce3 250Gb MCP           00E4
30    nForce4 MCP                 0052
31    nForce4 MCP-04              0034
32    nForce4 MCP51               0264
33    nForce4 MCP55               0368
34
35    This driver supports the 2 SMBuses that are included in the MCP of the
36    nForce2/3/4 chipsets.
37*/
38
39/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
40
41#include <linux/module.h>
42#include <linux/pci.h>
43#include <linux/kernel.h>
44#include <linux/stddef.h>
45#include <linux/sched.h>
46#include <linux/ioport.h>
47#include <linux/init.h>
48#include <linux/i2c.h>
49#include <linux/delay.h>
50#include <linux/slab.h>
51#include <asm/io.h>
52#include "version.h"
53#include "sensors_compat.h"
54
55MODULE_LICENSE("GPL");
56MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>");
57MODULE_DESCRIPTION("nForce2 SMBus driver");
58
59#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS
60#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS      0x0064
61#endif
62
63#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS
64#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS     0x0084
65#endif
66
67#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS
68#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS      0x00D4
69#endif
70
71#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS
72#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS     0x00E4
73#endif
74
75#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS
76#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS      0x0052
77#endif
78
79#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034
80#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS 0x0264
81#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS 0x0368
82
83
84struct nforce2_smbus {
85        struct i2c_adapter adapter;
86        int base;
87        int size;
88};
89
90
91/*
92 * nVidia nForce2 SMBus control register definitions
93 * (Newer incarnations use standard BARs 4 and 5 instead)
94 */
95#define NFORCE_PCI_SMB1 0x50
96#define NFORCE_PCI_SMB2 0x54
97
98
99/*
100 * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
101 */
102#define NVIDIA_SMB_PRTCL        (smbus->base + 0x00)    /* protocol, PEC */
103#define NVIDIA_SMB_STS          (smbus->base + 0x01)    /* status */
104#define NVIDIA_SMB_ADDR         (smbus->base + 0x02)    /* address */
105#define NVIDIA_SMB_CMD          (smbus->base + 0x03)    /* command */
106#define NVIDIA_SMB_DATA         (smbus->base + 0x04)    /* 32 data registers */
107#define NVIDIA_SMB_BCNT         (smbus->base + 0x24)    /* number of data bytes */
108#define NVIDIA_SMB_ALRM_A       (smbus->base + 0x25)    /* alarm address */
109#define NVIDIA_SMB_ALRM_D       (smbus->base + 0x26)    /* 2 bytes alarm data */
110
111#define NVIDIA_SMB_STS_DONE     0x80
112#define NVIDIA_SMB_STS_ALRM     0x40
113#define NVIDIA_SMB_STS_RES      0x20
114#define NVIDIA_SMB_STS_STATUS   0x1f
115
116#define NVIDIA_SMB_PRTCL_WRITE                  0x00
117#define NVIDIA_SMB_PRTCL_READ                   0x01
118#define NVIDIA_SMB_PRTCL_QUICK                  0x02
119#define NVIDIA_SMB_PRTCL_BYTE                   0x04
120#define NVIDIA_SMB_PRTCL_BYTE_DATA              0x06
121#define NVIDIA_SMB_PRTCL_WORD_DATA              0x08
122#define NVIDIA_SMB_PRTCL_BLOCK_DATA             0x0a
123#define NVIDIA_SMB_PRTCL_PROC_CALL              0x0c
124#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL        0x0d
125#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA         0x4a
126#define NVIDIA_SMB_PRTCL_PEC                    0x80
127
128static struct pci_driver nforce2_driver;
129
130static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
131                       unsigned short flags, char read_write,
132                       u8 command, int size, union i2c_smbus_data *data);
133/*
134static int nforce2_block_transaction(union i2c_smbus_data *data,
135                                  char read_write, int i2c_enable);
136 */
137static u32 nforce2_func(struct i2c_adapter *adapter);
138
139
140static struct i2c_algorithm smbus_algorithm = {
141        .name = "Non-I2C SMBus adapter",
142        .id = I2C_ALGO_SMBUS,
143        .smbus_xfer = nforce2_access,
144        .functionality = nforce2_func,
145};
146
147/* Return -1 on error. See smbus.h for more information */
148s32 nforce2_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
149                char read_write, u8 command, int size,
150                union i2c_smbus_data * data)
151{
152        struct nforce2_smbus *smbus = adap->algo_data;
153        unsigned char protocol, pec, temp;
154        unsigned char len = 0; /* to keep the compiler quiet */
155        int i;
156
157        protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : NVIDIA_SMB_PRTCL_WRITE;
158        pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0;
159
160        switch (size) {
161
162                case I2C_SMBUS_QUICK:
163                        protocol |= NVIDIA_SMB_PRTCL_QUICK;
164                        read_write = I2C_SMBUS_WRITE;
165                        break;
166
167                case I2C_SMBUS_BYTE:
168                        if (read_write == I2C_SMBUS_WRITE)
169                                outb_p(command, NVIDIA_SMB_CMD);
170                        protocol |= NVIDIA_SMB_PRTCL_BYTE;
171                        break;
172
173                case I2C_SMBUS_BYTE_DATA:
174                        outb_p(command, NVIDIA_SMB_CMD);
175                        if (read_write == I2C_SMBUS_WRITE)
176                                outb_p(data->byte, NVIDIA_SMB_DATA);
177                        protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA;
178                        break;
179
180                case I2C_SMBUS_WORD_DATA:
181                        outb_p(command, NVIDIA_SMB_CMD);
182                        if (read_write == I2C_SMBUS_WRITE) {
183                                 outb_p(data->word, NVIDIA_SMB_DATA);
184                                 outb_p(data->word >> 8, NVIDIA_SMB_DATA+1);
185                        }
186                        protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
187                        break;
188
189                case I2C_SMBUS_BLOCK_DATA:
190                        outb_p(command, NVIDIA_SMB_CMD);
191                        if (read_write == I2C_SMBUS_WRITE) {
192                                len = min_t(u8, data->block[0], 32);
193                                outb_p(len, NVIDIA_SMB_BCNT);
194                                for (i = 0; i < len; i++)
195                                        outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
196                        }
197                        protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
198                        break;
199
200                case I2C_SMBUS_I2C_BLOCK_DATA:
201                        len = min_t(u8, data->block[0], 32);
202                        outb_p(command, NVIDIA_SMB_CMD);
203                        outb_p(len, NVIDIA_SMB_BCNT);
204                        if (read_write == I2C_SMBUS_WRITE)
205                                for (i = 0; i < len; i++)
206                                        outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
207                        protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA;
208                        break;
209
210                case I2C_SMBUS_PROC_CALL:
211                        printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_PROC_CALL not supported!\n");
212                        return -1;
213
214                case I2C_SMBUS_BLOCK_PROC_CALL:
215                        printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
216                        return -1;
217
218                default:
219                        printk(KERN_WARNING "i2c-nforce2.c: Unsupported transaction %d\n", size);
220                        return -1;
221        }
222
223        outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
224        outb_p(protocol, NVIDIA_SMB_PRTCL);
225
226        temp = inb_p(NVIDIA_SMB_STS);
227
228        if (~temp & NVIDIA_SMB_STS_DONE) {
229                udelay(500);
230                temp = inb_p(NVIDIA_SMB_STS);
231        }
232        if (~temp & NVIDIA_SMB_STS_DONE) {
233                i2c_delay(HZ/100);
234                temp = inb_p(NVIDIA_SMB_STS);
235        }
236
237        if ((~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
238                printk(KERN_DEBUG "i2c-nforce2.o: SMBus Timeout! (0x%02x)\n",
239                       temp);
240                return -1;
241        }
242
243        if (read_write == I2C_SMBUS_WRITE)
244                return 0;
245
246        switch (size) {
247
248                case I2C_SMBUS_BYTE:
249                case I2C_SMBUS_BYTE_DATA:
250                        data->byte = inb_p(NVIDIA_SMB_DATA);
251                        break;
252
253                case I2C_SMBUS_WORD_DATA:
254                /* case I2C_SMBUS_PROC_CALL: not supported */
255                        data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
256                        break;
257
258                case I2C_SMBUS_BLOCK_DATA:
259                /* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */
260                        len = inb_p(NVIDIA_SMB_BCNT);
261                        len = min_t(u8, len, 32);
262                case I2C_SMBUS_I2C_BLOCK_DATA:
263                        for (i = 0; i < len; i++)
264                                data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
265                        data->block[0] = len;
266                        break;
267        }
268
269        return 0;
270}
271
272
273u32 nforce2_func(struct i2c_adapter *adapter)
274{
275        /* other functionality might be possible, but is not tested */
276        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
277            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* |
278            I2C_FUNC_SMBUS_BLOCK_DATA */;
279}
280
281static void nforce2_inc(struct i2c_adapter *adapter)
282{
283#ifdef MODULE
284        MOD_INC_USE_COUNT;
285#endif
286}
287
288static void nforce2_dec(struct i2c_adapter *adapter)
289{
290#ifdef MODULE
291        MOD_DEC_USE_COUNT;
292#endif
293}
294
295static struct pci_device_id nforce2_ids[] = {
296        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS,
297                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
298        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS,
299                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
300        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS,
301                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
302        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS,
303                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
304        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS,
305                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
306        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS,
307                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
308        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS,
309                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
310        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS,
311                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
312        { 0 }
313};
314
315
316static int __devinit nforce2_probe_smb(struct pci_dev *dev, int bar,
317        int alt_reg, struct nforce2_smbus *smbus, char *name)
318{
319        int error;
320
321        smbus->base = pci_resource_start(dev, bar);
322        if (smbus->base) {
323                smbus->size = pci_resource_len(dev, bar);
324        } else {
325                /* Older incarnations of the device used non-standard BARs */
326                u16 iobase;
327
328                if (pci_read_config_word(dev, alt_reg, &iobase)
329                    != PCIBIOS_SUCCESSFUL) {
330                        printk(KERN_ERR "i2c-nforce2.o: Error reading PCI "
331                               "config for %s\n", name);
332                        return -1;
333                }
334
335                smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
336                smbus->size = 8;
337        }
338
339        if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
340                printk (KERN_ERR "i2c-nforce2.o: Error requesting region %02x .. %02X for %s\n", smbus->base, smbus->base+smbus->size-1, name);
341                return -1;
342        }
343
344        sprintf(smbus->adapter.name, "SMBus nForce2 adapter at %04x", smbus->base);
345        smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_NFORCE2;
346        smbus->adapter.algo = &smbus_algorithm;
347        smbus->adapter.algo_data = smbus;
348        smbus->adapter.inc_use = nforce2_inc;
349        smbus->adapter.dec_use = nforce2_dec;
350
351        error = i2c_add_adapter(&smbus->adapter);
352        if (error) {
353                printk(KERN_WARNING "i2c-nforce2.o: Failed to register adapter.\n");
354                release_region(smbus->base, smbus->size);
355                return -1;
356        }
357        printk(KERN_INFO "i2c-nforce2.o: nForce2 SMBus adapter at %#x\n", smbus->base);
358        return 0;
359}
360
361
362static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
363{
364        struct nforce2_smbus *smbuses;
365        int res1, res2;
366
367        /* we support 2 SMBus adapters */
368        if (!(smbuses = kmalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL)))
369                return -ENOMEM;
370        memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
371        pci_set_drvdata(dev, smbuses);
372
373        /* SMBus adapter 1 */
374        res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
375        if (res1 < 0) {
376                printk (KERN_ERR "i2c-nforce2.o: Error probing SMB1.\n");
377                smbuses[0].base = 0;    /* to have a check value */
378        }
379        /* SMBus adapter 2 */
380        res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2");
381        if (res2 < 0) {
382                printk (KERN_ERR "i2c-nforce2.o: Error probing SMB2.\n");
383                smbuses[1].base = 0;    /* to have a check value */
384        }
385        if ((res1 < 0) && (res2 < 0)) {
386                /* we did not find even one of the SMBuses, so we give up */
387                kfree(smbuses);
388                return -ENODEV;
389        }
390
391        return 0;
392}
393
394
395static void __devexit nforce2_remove(struct pci_dev *dev)
396{
397        struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
398
399        if (smbuses[0].base) {
400                i2c_del_adapter(&smbuses[0].adapter);
401                release_region(smbuses[0].base, smbuses[0].size);
402        }
403        if (smbuses[1].base) {
404                i2c_del_adapter(&smbuses[1].adapter);
405                release_region(smbuses[1].base, smbuses[1].size);
406        }
407        kfree(smbuses);
408}
409
410static struct pci_driver nforce2_driver = {
411        .name           = "nForce2 SMBus",
412        .id_table       = nforce2_ids,
413        .probe          = nforce2_probe,
414        .remove         = __devexit_p(nforce2_remove),
415};
416
417int __init nforce2_init(void)
418{
419        printk(KERN_INFO "i2c-nforce2.o version %s (%s)\n", LM_VERSION, LM_DATE);
420        return pci_module_init(&nforce2_driver);
421}
422
423void __exit nforce2_exit(void)
424{
425        pci_unregister_driver(&nforce2_driver);
426}
427
428module_init(nforce2_init);
429module_exit(nforce2_exit);
430
Note: See TracBrowser for help on using the browser.