1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun SMBus driver for nVidia nForce2 MCP
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Added nForce3 Pro 150 Thomas Leibold <thomas@plx.com>,
6*4882a593Smuzhiyun Ported to 2.5 Patrick Dreker <patrick@dreker.de>,
7*4882a593Smuzhiyun Copyright (c) 2003 Hans-Frieder Vogt <hfvogt@arcor.de>,
8*4882a593Smuzhiyun Based on
9*4882a593Smuzhiyun SMBus 2.0 driver for AMD-8111 IO-Hub
10*4882a593Smuzhiyun Copyright (c) 2002 Vojtech Pavlik
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun /*
15*4882a593Smuzhiyun SUPPORTED DEVICES PCI ID
16*4882a593Smuzhiyun nForce2 MCP 0064
17*4882a593Smuzhiyun nForce2 Ultra 400 MCP 0084
18*4882a593Smuzhiyun nForce3 Pro150 MCP 00D4
19*4882a593Smuzhiyun nForce3 250Gb MCP 00E4
20*4882a593Smuzhiyun nForce4 MCP 0052
21*4882a593Smuzhiyun nForce4 MCP-04 0034
22*4882a593Smuzhiyun nForce MCP51 0264
23*4882a593Smuzhiyun nForce MCP55 0368
24*4882a593Smuzhiyun nForce MCP61 03EB
25*4882a593Smuzhiyun nForce MCP65 0446
26*4882a593Smuzhiyun nForce MCP67 0542
27*4882a593Smuzhiyun nForce MCP73 07D8
28*4882a593Smuzhiyun nForce MCP78S 0752
29*4882a593Smuzhiyun nForce MCP79 0AA2
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun This driver supports the 2 SMBuses that are included in the MCP of the
32*4882a593Smuzhiyun nForce2/3/4/5xx chipsets.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* Note: we assume there can only be one nForce2, with two SMBus interfaces */
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #include <linux/module.h>
38*4882a593Smuzhiyun #include <linux/pci.h>
39*4882a593Smuzhiyun #include <linux/kernel.h>
40*4882a593Smuzhiyun #include <linux/stddef.h>
41*4882a593Smuzhiyun #include <linux/ioport.h>
42*4882a593Smuzhiyun #include <linux/i2c.h>
43*4882a593Smuzhiyun #include <linux/delay.h>
44*4882a593Smuzhiyun #include <linux/dmi.h>
45*4882a593Smuzhiyun #include <linux/acpi.h>
46*4882a593Smuzhiyun #include <linux/slab.h>
47*4882a593Smuzhiyun #include <linux/io.h>
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun MODULE_LICENSE("GPL");
50*4882a593Smuzhiyun MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
51*4882a593Smuzhiyun MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun struct nforce2_smbus {
55*4882a593Smuzhiyun struct i2c_adapter adapter;
56*4882a593Smuzhiyun int base;
57*4882a593Smuzhiyun int size;
58*4882a593Smuzhiyun int blockops;
59*4882a593Smuzhiyun int can_abort;
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun * nVidia nForce2 SMBus control register definitions
65*4882a593Smuzhiyun * (Newer incarnations use standard BARs 4 and 5 instead)
66*4882a593Smuzhiyun */
67*4882a593Smuzhiyun #define NFORCE_PCI_SMB1 0x50
68*4882a593Smuzhiyun #define NFORCE_PCI_SMB2 0x54
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
73*4882a593Smuzhiyun */
74*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL (smbus->base + 0x00) /* protocol, PEC */
75*4882a593Smuzhiyun #define NVIDIA_SMB_STS (smbus->base + 0x01) /* status */
76*4882a593Smuzhiyun #define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */
77*4882a593Smuzhiyun #define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */
78*4882a593Smuzhiyun #define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */
79*4882a593Smuzhiyun #define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data
80*4882a593Smuzhiyun bytes */
81*4882a593Smuzhiyun #define NVIDIA_SMB_STATUS_ABRT (smbus->base + 0x3c) /* register used to
82*4882a593Smuzhiyun check the status of
83*4882a593Smuzhiyun the abort command */
84*4882a593Smuzhiyun #define NVIDIA_SMB_CTRL (smbus->base + 0x3e) /* control register */
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun #define NVIDIA_SMB_STATUS_ABRT_STS 0x01 /* Bit to notify that
87*4882a593Smuzhiyun abort succeeded */
88*4882a593Smuzhiyun #define NVIDIA_SMB_CTRL_ABORT 0x20
89*4882a593Smuzhiyun #define NVIDIA_SMB_STS_DONE 0x80
90*4882a593Smuzhiyun #define NVIDIA_SMB_STS_ALRM 0x40
91*4882a593Smuzhiyun #define NVIDIA_SMB_STS_RES 0x20
92*4882a593Smuzhiyun #define NVIDIA_SMB_STS_STATUS 0x1f
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_WRITE 0x00
95*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_READ 0x01
96*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_QUICK 0x02
97*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_BYTE 0x04
98*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06
99*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_WORD_DATA 0x08
100*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a
101*4882a593Smuzhiyun #define NVIDIA_SMB_PRTCL_PEC 0x80
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /* Misc definitions */
104*4882a593Smuzhiyun #define MAX_TIMEOUT 100
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* We disable the second SMBus channel on these boards */
107*4882a593Smuzhiyun static const struct dmi_system_id nforce2_dmi_blacklist2[] = {
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun .ident = "DFI Lanparty NF4 Expert",
110*4882a593Smuzhiyun .matches = {
111*4882a593Smuzhiyun DMI_MATCH(DMI_BOARD_VENDOR, "DFI Corp,LTD"),
112*4882a593Smuzhiyun DMI_MATCH(DMI_BOARD_NAME, "LP UT NF4 Expert"),
113*4882a593Smuzhiyun },
114*4882a593Smuzhiyun },
115*4882a593Smuzhiyun { }
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun static struct pci_driver nforce2_driver;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* For multiplexing support, we need a global reference to the 1st
121*4882a593Smuzhiyun SMBus channel */
122*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_I2C_NFORCE2_S4985)
123*4882a593Smuzhiyun struct i2c_adapter *nforce2_smbus;
124*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(nforce2_smbus);
125*4882a593Smuzhiyun
nforce2_set_reference(struct i2c_adapter * adap)126*4882a593Smuzhiyun static void nforce2_set_reference(struct i2c_adapter *adap)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun nforce2_smbus = adap;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun #else
nforce2_set_reference(struct i2c_adapter * adap)131*4882a593Smuzhiyun static inline void nforce2_set_reference(struct i2c_adapter *adap) { }
132*4882a593Smuzhiyun #endif
133*4882a593Smuzhiyun
nforce2_abort(struct i2c_adapter * adap)134*4882a593Smuzhiyun static void nforce2_abort(struct i2c_adapter *adap)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun struct nforce2_smbus *smbus = adap->algo_data;
137*4882a593Smuzhiyun int timeout = 0;
138*4882a593Smuzhiyun unsigned char temp;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun dev_dbg(&adap->dev, "Aborting current transaction\n");
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun outb_p(NVIDIA_SMB_CTRL_ABORT, NVIDIA_SMB_CTRL);
143*4882a593Smuzhiyun do {
144*4882a593Smuzhiyun msleep(1);
145*4882a593Smuzhiyun temp = inb_p(NVIDIA_SMB_STATUS_ABRT);
146*4882a593Smuzhiyun } while (!(temp & NVIDIA_SMB_STATUS_ABRT_STS) &&
147*4882a593Smuzhiyun (timeout++ < MAX_TIMEOUT));
148*4882a593Smuzhiyun if (!(temp & NVIDIA_SMB_STATUS_ABRT_STS))
149*4882a593Smuzhiyun dev_err(&adap->dev, "Can't reset the smbus\n");
150*4882a593Smuzhiyun outb_p(NVIDIA_SMB_STATUS_ABRT_STS, NVIDIA_SMB_STATUS_ABRT);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
nforce2_check_status(struct i2c_adapter * adap)153*4882a593Smuzhiyun static int nforce2_check_status(struct i2c_adapter *adap)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun struct nforce2_smbus *smbus = adap->algo_data;
156*4882a593Smuzhiyun int timeout = 0;
157*4882a593Smuzhiyun unsigned char temp;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun do {
160*4882a593Smuzhiyun msleep(1);
161*4882a593Smuzhiyun temp = inb_p(NVIDIA_SMB_STS);
162*4882a593Smuzhiyun } while ((!temp) && (timeout++ < MAX_TIMEOUT));
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (timeout > MAX_TIMEOUT) {
165*4882a593Smuzhiyun dev_dbg(&adap->dev, "SMBus Timeout!\n");
166*4882a593Smuzhiyun if (smbus->can_abort)
167*4882a593Smuzhiyun nforce2_abort(adap);
168*4882a593Smuzhiyun return -ETIMEDOUT;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
171*4882a593Smuzhiyun dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp);
172*4882a593Smuzhiyun return -EIO;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun return 0;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* Return negative errno on error */
nforce2_access(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)178*4882a593Smuzhiyun static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
179*4882a593Smuzhiyun unsigned short flags, char read_write,
180*4882a593Smuzhiyun u8 command, int size, union i2c_smbus_data *data)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun struct nforce2_smbus *smbus = adap->algo_data;
183*4882a593Smuzhiyun unsigned char protocol, pec;
184*4882a593Smuzhiyun u8 len;
185*4882a593Smuzhiyun int i, status;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
188*4882a593Smuzhiyun NVIDIA_SMB_PRTCL_WRITE;
189*4882a593Smuzhiyun pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun switch (size) {
192*4882a593Smuzhiyun case I2C_SMBUS_QUICK:
193*4882a593Smuzhiyun protocol |= NVIDIA_SMB_PRTCL_QUICK;
194*4882a593Smuzhiyun read_write = I2C_SMBUS_WRITE;
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun case I2C_SMBUS_BYTE:
198*4882a593Smuzhiyun if (read_write == I2C_SMBUS_WRITE)
199*4882a593Smuzhiyun outb_p(command, NVIDIA_SMB_CMD);
200*4882a593Smuzhiyun protocol |= NVIDIA_SMB_PRTCL_BYTE;
201*4882a593Smuzhiyun break;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun case I2C_SMBUS_BYTE_DATA:
204*4882a593Smuzhiyun outb_p(command, NVIDIA_SMB_CMD);
205*4882a593Smuzhiyun if (read_write == I2C_SMBUS_WRITE)
206*4882a593Smuzhiyun outb_p(data->byte, NVIDIA_SMB_DATA);
207*4882a593Smuzhiyun protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA;
208*4882a593Smuzhiyun break;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun case I2C_SMBUS_WORD_DATA:
211*4882a593Smuzhiyun outb_p(command, NVIDIA_SMB_CMD);
212*4882a593Smuzhiyun if (read_write == I2C_SMBUS_WRITE) {
213*4882a593Smuzhiyun outb_p(data->word, NVIDIA_SMB_DATA);
214*4882a593Smuzhiyun outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun case I2C_SMBUS_BLOCK_DATA:
220*4882a593Smuzhiyun outb_p(command, NVIDIA_SMB_CMD);
221*4882a593Smuzhiyun if (read_write == I2C_SMBUS_WRITE) {
222*4882a593Smuzhiyun len = data->block[0];
223*4882a593Smuzhiyun if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
224*4882a593Smuzhiyun dev_err(&adap->dev,
225*4882a593Smuzhiyun "Transaction failed (requested block size: %d)\n",
226*4882a593Smuzhiyun len);
227*4882a593Smuzhiyun return -EINVAL;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun outb_p(len, NVIDIA_SMB_BCNT);
230*4882a593Smuzhiyun for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
231*4882a593Smuzhiyun outb_p(data->block[i + 1],
232*4882a593Smuzhiyun NVIDIA_SMB_DATA + i);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
235*4882a593Smuzhiyun break;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun default:
238*4882a593Smuzhiyun dev_err(&adap->dev, "Unsupported transaction %d\n", size);
239*4882a593Smuzhiyun return -EOPNOTSUPP;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
243*4882a593Smuzhiyun outb_p(protocol, NVIDIA_SMB_PRTCL);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun status = nforce2_check_status(adap);
246*4882a593Smuzhiyun if (status)
247*4882a593Smuzhiyun return status;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (read_write == I2C_SMBUS_WRITE)
250*4882a593Smuzhiyun return 0;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun switch (size) {
253*4882a593Smuzhiyun case I2C_SMBUS_BYTE:
254*4882a593Smuzhiyun case I2C_SMBUS_BYTE_DATA:
255*4882a593Smuzhiyun data->byte = inb_p(NVIDIA_SMB_DATA);
256*4882a593Smuzhiyun break;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun case I2C_SMBUS_WORD_DATA:
259*4882a593Smuzhiyun data->word = inb_p(NVIDIA_SMB_DATA) |
260*4882a593Smuzhiyun (inb_p(NVIDIA_SMB_DATA + 1) << 8);
261*4882a593Smuzhiyun break;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun case I2C_SMBUS_BLOCK_DATA:
264*4882a593Smuzhiyun len = inb_p(NVIDIA_SMB_BCNT);
265*4882a593Smuzhiyun if ((len <= 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
266*4882a593Smuzhiyun dev_err(&adap->dev,
267*4882a593Smuzhiyun "Transaction failed (received block size: 0x%02x)\n",
268*4882a593Smuzhiyun len);
269*4882a593Smuzhiyun return -EPROTO;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun for (i = 0; i < len; i++)
272*4882a593Smuzhiyun data->block[i + 1] = inb_p(NVIDIA_SMB_DATA + i);
273*4882a593Smuzhiyun data->block[0] = len;
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun return 0;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun
nforce2_func(struct i2c_adapter * adapter)281*4882a593Smuzhiyun static u32 nforce2_func(struct i2c_adapter *adapter)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun /* other functionality might be possible, but is not tested */
284*4882a593Smuzhiyun return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
285*4882a593Smuzhiyun I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
286*4882a593Smuzhiyun I2C_FUNC_SMBUS_PEC |
287*4882a593Smuzhiyun (((struct nforce2_smbus *)adapter->algo_data)->blockops ?
288*4882a593Smuzhiyun I2C_FUNC_SMBUS_BLOCK_DATA : 0);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun static const struct i2c_algorithm smbus_algorithm = {
292*4882a593Smuzhiyun .smbus_xfer = nforce2_access,
293*4882a593Smuzhiyun .functionality = nforce2_func,
294*4882a593Smuzhiyun };
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static const struct pci_device_id nforce2_ids[] = {
298*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
299*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
300*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
301*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
302*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },
303*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
304*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
305*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
306*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
307*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
308*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) },
309*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) },
310*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) },
311*4882a593Smuzhiyun { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) },
312*4882a593Smuzhiyun { 0 }
313*4882a593Smuzhiyun };
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, nforce2_ids);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun
nforce2_probe_smb(struct pci_dev * dev,int bar,int alt_reg,struct nforce2_smbus * smbus,const char * name)318*4882a593Smuzhiyun static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
319*4882a593Smuzhiyun struct nforce2_smbus *smbus, const char *name)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun int error;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun smbus->base = pci_resource_start(dev, bar);
324*4882a593Smuzhiyun if (smbus->base) {
325*4882a593Smuzhiyun smbus->size = pci_resource_len(dev, bar);
326*4882a593Smuzhiyun } else {
327*4882a593Smuzhiyun /* Older incarnations of the device used non-standard BARs */
328*4882a593Smuzhiyun u16 iobase;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun if (pci_read_config_word(dev, alt_reg, &iobase)
331*4882a593Smuzhiyun != PCIBIOS_SUCCESSFUL) {
332*4882a593Smuzhiyun dev_err(&dev->dev, "Error reading PCI config for %s\n",
333*4882a593Smuzhiyun name);
334*4882a593Smuzhiyun return -EIO;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
338*4882a593Smuzhiyun smbus->size = 64;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun error = acpi_check_region(smbus->base, smbus->size,
342*4882a593Smuzhiyun nforce2_driver.name);
343*4882a593Smuzhiyun if (error)
344*4882a593Smuzhiyun return error;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
347*4882a593Smuzhiyun dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
348*4882a593Smuzhiyun smbus->base, smbus->base+smbus->size-1, name);
349*4882a593Smuzhiyun return -EBUSY;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun smbus->adapter.owner = THIS_MODULE;
352*4882a593Smuzhiyun smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
353*4882a593Smuzhiyun smbus->adapter.algo = &smbus_algorithm;
354*4882a593Smuzhiyun smbus->adapter.algo_data = smbus;
355*4882a593Smuzhiyun smbus->adapter.dev.parent = &dev->dev;
356*4882a593Smuzhiyun snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
357*4882a593Smuzhiyun "SMBus nForce2 adapter at %04x", smbus->base);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun error = i2c_add_adapter(&smbus->adapter);
360*4882a593Smuzhiyun if (error) {
361*4882a593Smuzhiyun release_region(smbus->base, smbus->size);
362*4882a593Smuzhiyun return error;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n",
365*4882a593Smuzhiyun smbus->base);
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun
nforce2_probe(struct pci_dev * dev,const struct pci_device_id * id)370*4882a593Smuzhiyun static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun struct nforce2_smbus *smbuses;
373*4882a593Smuzhiyun int res1, res2;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun /* we support 2 SMBus adapters */
376*4882a593Smuzhiyun smbuses = kcalloc(2, sizeof(struct nforce2_smbus), GFP_KERNEL);
377*4882a593Smuzhiyun if (!smbuses)
378*4882a593Smuzhiyun return -ENOMEM;
379*4882a593Smuzhiyun pci_set_drvdata(dev, smbuses);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun switch (dev->device) {
382*4882a593Smuzhiyun case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS:
383*4882a593Smuzhiyun case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
384*4882a593Smuzhiyun case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
385*4882a593Smuzhiyun smbuses[0].blockops = 1;
386*4882a593Smuzhiyun smbuses[1].blockops = 1;
387*4882a593Smuzhiyun smbuses[0].can_abort = 1;
388*4882a593Smuzhiyun smbuses[1].can_abort = 1;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* SMBus adapter 1 */
392*4882a593Smuzhiyun res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
393*4882a593Smuzhiyun if (res1 < 0)
394*4882a593Smuzhiyun smbuses[0].base = 0; /* to have a check value */
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* SMBus adapter 2 */
397*4882a593Smuzhiyun if (dmi_check_system(nforce2_dmi_blacklist2)) {
398*4882a593Smuzhiyun dev_err(&dev->dev, "Disabling SMB2 for safety reasons.\n");
399*4882a593Smuzhiyun res2 = -EPERM;
400*4882a593Smuzhiyun smbuses[1].base = 0;
401*4882a593Smuzhiyun } else {
402*4882a593Smuzhiyun res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1],
403*4882a593Smuzhiyun "SMB2");
404*4882a593Smuzhiyun if (res2 < 0)
405*4882a593Smuzhiyun smbuses[1].base = 0; /* to have a check value */
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun if ((res1 < 0) && (res2 < 0)) {
409*4882a593Smuzhiyun /* we did not find even one of the SMBuses, so we give up */
410*4882a593Smuzhiyun kfree(smbuses);
411*4882a593Smuzhiyun return -ENODEV;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun nforce2_set_reference(&smbuses[0].adapter);
415*4882a593Smuzhiyun return 0;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun
nforce2_remove(struct pci_dev * dev)419*4882a593Smuzhiyun static void nforce2_remove(struct pci_dev *dev)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun struct nforce2_smbus *smbuses = pci_get_drvdata(dev);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun nforce2_set_reference(NULL);
424*4882a593Smuzhiyun if (smbuses[0].base) {
425*4882a593Smuzhiyun i2c_del_adapter(&smbuses[0].adapter);
426*4882a593Smuzhiyun release_region(smbuses[0].base, smbuses[0].size);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun if (smbuses[1].base) {
429*4882a593Smuzhiyun i2c_del_adapter(&smbuses[1].adapter);
430*4882a593Smuzhiyun release_region(smbuses[1].base, smbuses[1].size);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun kfree(smbuses);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun static struct pci_driver nforce2_driver = {
436*4882a593Smuzhiyun .name = "nForce2_smbus",
437*4882a593Smuzhiyun .id_table = nforce2_ids,
438*4882a593Smuzhiyun .probe = nforce2_probe,
439*4882a593Smuzhiyun .remove = nforce2_remove,
440*4882a593Smuzhiyun };
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun module_pci_driver(nforce2_driver);
443