1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * SMBus 2.0 driver for AMD-8111 IO-Hub.
4 *
5 * Copyright (c) 2002 Vojtech Pavlik
6 */
7
8#include <linux/module.h>
9#include <linux/pci.h>
10#include <linux/kernel.h>
11#include <linux/stddef.h>
12#include <linux/ioport.h>
13#include <linux/i2c.h>
14#include <linux/delay.h>
15#include <linux/acpi.h>
16#include <linux/slab.h>
17#include <linux/io.h>
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
21MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
22
23struct amd_smbus {
24 struct pci_dev *dev;
25 struct i2c_adapter adapter;
26 int base;
27 int size;
28};
29
30static struct pci_driver amd8111_driver;
31
32/*
33 * AMD PCI control registers definitions.
34 */
35
36#define AMD_PCI_MISC 0x48
37
38#define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */
39#define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */
40#define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */
41
42/*
43 * ACPI 2.0 chapter 13 PCI interface definitions.
44 */
45
46#define AMD_EC_DATA 0x00 /* data register */
47#define AMD_EC_SC 0x04 /* status of controller */
48#define AMD_EC_CMD 0x04 /* command register */
49#define AMD_EC_ICR 0x08 /* interrupt control register */
50
51#define AMD_EC_SC_SMI 0x04 /* smi event pending */
52#define AMD_EC_SC_SCI 0x02 /* sci event pending */
53#define AMD_EC_SC_BURST 0x01 /* burst mode enabled */
54#define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */
55#define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */
56#define AMD_EC_SC_OBF 0x01 /* data ready for host */
57
58#define AMD_EC_CMD_RD 0x80 /* read EC */
59#define AMD_EC_CMD_WR 0x81 /* write EC */
60#define AMD_EC_CMD_BE 0x82 /* enable burst mode */
61#define AMD_EC_CMD_BD 0x83 /* disable burst mode */
62#define AMD_EC_CMD_QR 0x84 /* query EC */
63
64/*
65 * ACPI 2.0 chapter 13 access of registers of the EC
66 */
67
68static int amd_ec_wait_write(struct amd_smbus *smbus)
69{
70 int timeout = 500;
71
72 while ((inb(port: smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
73 udelay(1);
74
75 if (!timeout) {
76 dev_warn(&smbus->dev->dev,
77 "Timeout while waiting for IBF to clear\n");
78 return -ETIMEDOUT;
79 }
80
81 return 0;
82}
83
84static int amd_ec_wait_read(struct amd_smbus *smbus)
85{
86 int timeout = 500;
87
88 while ((~inb(port: smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
89 udelay(1);
90
91 if (!timeout) {
92 dev_warn(&smbus->dev->dev,
93 "Timeout while waiting for OBF to set\n");
94 return -ETIMEDOUT;
95 }
96
97 return 0;
98}
99
100static int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
101 unsigned char *data)
102{
103 int status;
104
105 status = amd_ec_wait_write(smbus);
106 if (status)
107 return status;
108 outb(AMD_EC_CMD_RD, port: smbus->base + AMD_EC_CMD);
109
110 status = amd_ec_wait_write(smbus);
111 if (status)
112 return status;
113 outb(value: address, port: smbus->base + AMD_EC_DATA);
114
115 status = amd_ec_wait_read(smbus);
116 if (status)
117 return status;
118 *data = inb(port: smbus->base + AMD_EC_DATA);
119
120 return 0;
121}
122
123static int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
124 unsigned char data)
125{
126 int status;
127
128 status = amd_ec_wait_write(smbus);
129 if (status)
130 return status;
131 outb(AMD_EC_CMD_WR, port: smbus->base + AMD_EC_CMD);
132
133 status = amd_ec_wait_write(smbus);
134 if (status)
135 return status;
136 outb(value: address, port: smbus->base + AMD_EC_DATA);
137
138 status = amd_ec_wait_write(smbus);
139 if (status)
140 return status;
141 outb(value: data, port: smbus->base + AMD_EC_DATA);
142
143 return 0;
144}
145
146/*
147 * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
148 */
149
150#define AMD_SMB_PRTCL 0x00 /* protocol, PEC */
151#define AMD_SMB_STS 0x01 /* status */
152#define AMD_SMB_ADDR 0x02 /* address */
153#define AMD_SMB_CMD 0x03 /* command */
154#define AMD_SMB_DATA 0x04 /* 32 data registers */
155#define AMD_SMB_BCNT 0x24 /* number of data bytes */
156#define AMD_SMB_ALRM_A 0x25 /* alarm address */
157#define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
158
159#define AMD_SMB_STS_DONE 0x80
160#define AMD_SMB_STS_ALRM 0x40
161#define AMD_SMB_STS_RES 0x20
162#define AMD_SMB_STS_STATUS 0x1f
163
164#define AMD_SMB_STATUS_OK 0x00
165#define AMD_SMB_STATUS_FAIL 0x07
166#define AMD_SMB_STATUS_DNAK 0x10
167#define AMD_SMB_STATUS_DERR 0x11
168#define AMD_SMB_STATUS_CMD_DENY 0x12
169#define AMD_SMB_STATUS_UNKNOWN 0x13
170#define AMD_SMB_STATUS_ACC_DENY 0x17
171#define AMD_SMB_STATUS_TIMEOUT 0x18
172#define AMD_SMB_STATUS_NOTSUP 0x19
173#define AMD_SMB_STATUS_BUSY 0x1A
174#define AMD_SMB_STATUS_PEC 0x1F
175
176#define AMD_SMB_PRTCL_WRITE 0x00
177#define AMD_SMB_PRTCL_READ 0x01
178#define AMD_SMB_PRTCL_QUICK 0x02
179#define AMD_SMB_PRTCL_BYTE 0x04
180#define AMD_SMB_PRTCL_BYTE_DATA 0x06
181#define AMD_SMB_PRTCL_WORD_DATA 0x08
182#define AMD_SMB_PRTCL_BLOCK_DATA 0x0a
183#define AMD_SMB_PRTCL_PROC_CALL 0x0c
184#define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
185#define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
186#define AMD_SMB_PRTCL_PEC 0x80
187
188
189static s32 amd8111_access(struct i2c_adapter *adap, u16 addr,
190 unsigned short flags, char read_write, u8 command, int size,
191 union i2c_smbus_data *data)
192{
193 struct amd_smbus *smbus = adap->algo_data;
194 unsigned char protocol, len, pec, temp[2];
195 int i, status;
196
197 protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ
198 : AMD_SMB_PRTCL_WRITE;
199 pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
200
201 switch (size) {
202 case I2C_SMBUS_QUICK:
203 protocol |= AMD_SMB_PRTCL_QUICK;
204 read_write = I2C_SMBUS_WRITE;
205 break;
206
207 case I2C_SMBUS_BYTE:
208 if (read_write == I2C_SMBUS_WRITE) {
209 status = amd_ec_write(smbus, AMD_SMB_CMD,
210 data: command);
211 if (status)
212 return status;
213 }
214 protocol |= AMD_SMB_PRTCL_BYTE;
215 break;
216
217 case I2C_SMBUS_BYTE_DATA:
218 status = amd_ec_write(smbus, AMD_SMB_CMD, data: command);
219 if (status)
220 return status;
221 if (read_write == I2C_SMBUS_WRITE) {
222 status = amd_ec_write(smbus, AMD_SMB_DATA,
223 data: data->byte);
224 if (status)
225 return status;
226 }
227 protocol |= AMD_SMB_PRTCL_BYTE_DATA;
228 break;
229
230 case I2C_SMBUS_WORD_DATA:
231 status = amd_ec_write(smbus, AMD_SMB_CMD, data: command);
232 if (status)
233 return status;
234 if (read_write == I2C_SMBUS_WRITE) {
235 status = amd_ec_write(smbus, AMD_SMB_DATA,
236 data: data->word & 0xff);
237 if (status)
238 return status;
239 status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
240 data: data->word >> 8);
241 if (status)
242 return status;
243 }
244 protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
245 break;
246
247 case I2C_SMBUS_BLOCK_DATA:
248 status = amd_ec_write(smbus, AMD_SMB_CMD, data: command);
249 if (status)
250 return status;
251 if (read_write == I2C_SMBUS_WRITE) {
252 len = min_t(u8, data->block[0],
253 I2C_SMBUS_BLOCK_MAX);
254 status = amd_ec_write(smbus, AMD_SMB_BCNT, data: len);
255 if (status)
256 return status;
257 for (i = 0; i < len; i++) {
258 status =
259 amd_ec_write(smbus, AMD_SMB_DATA + i,
260 data: data->block[i + 1]);
261 if (status)
262 return status;
263 }
264 }
265 protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
266 break;
267
268 case I2C_SMBUS_I2C_BLOCK_DATA:
269 len = min_t(u8, data->block[0],
270 I2C_SMBUS_BLOCK_MAX);
271 status = amd_ec_write(smbus, AMD_SMB_CMD, data: command);
272 if (status)
273 return status;
274 status = amd_ec_write(smbus, AMD_SMB_BCNT, data: len);
275 if (status)
276 return status;
277 if (read_write == I2C_SMBUS_WRITE)
278 for (i = 0; i < len; i++) {
279 status =
280 amd_ec_write(smbus, AMD_SMB_DATA + i,
281 data: data->block[i + 1]);
282 if (status)
283 return status;
284 }
285 protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
286 break;
287
288 case I2C_SMBUS_PROC_CALL:
289 status = amd_ec_write(smbus, AMD_SMB_CMD, data: command);
290 if (status)
291 return status;
292 status = amd_ec_write(smbus, AMD_SMB_DATA,
293 data: data->word & 0xff);
294 if (status)
295 return status;
296 status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
297 data: data->word >> 8);
298 if (status)
299 return status;
300 protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
301 read_write = I2C_SMBUS_READ;
302 break;
303
304 case I2C_SMBUS_BLOCK_PROC_CALL:
305 len = min_t(u8, data->block[0],
306 I2C_SMBUS_BLOCK_MAX - 1);
307 status = amd_ec_write(smbus, AMD_SMB_CMD, data: command);
308 if (status)
309 return status;
310 status = amd_ec_write(smbus, AMD_SMB_BCNT, data: len);
311 if (status)
312 return status;
313 for (i = 0; i < len; i++) {
314 status = amd_ec_write(smbus, AMD_SMB_DATA + i,
315 data: data->block[i + 1]);
316 if (status)
317 return status;
318 }
319 protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
320 read_write = I2C_SMBUS_READ;
321 break;
322
323 default:
324 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
325 return -EOPNOTSUPP;
326 }
327
328 status = amd_ec_write(smbus, AMD_SMB_ADDR, data: addr << 1);
329 if (status)
330 return status;
331 status = amd_ec_write(smbus, AMD_SMB_PRTCL, data: protocol);
332 if (status)
333 return status;
334
335 status = amd_ec_read(smbus, AMD_SMB_STS, data: temp + 0);
336 if (status)
337 return status;
338
339 if (~temp[0] & AMD_SMB_STS_DONE) {
340 udelay(500);
341 status = amd_ec_read(smbus, AMD_SMB_STS, data: temp + 0);
342 if (status)
343 return status;
344 }
345
346 if (~temp[0] & AMD_SMB_STS_DONE) {
347 msleep(msecs: 1);
348 status = amd_ec_read(smbus, AMD_SMB_STS, data: temp + 0);
349 if (status)
350 return status;
351 }
352
353 if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
354 return -EIO;
355
356 if (read_write == I2C_SMBUS_WRITE)
357 return 0;
358
359 switch (size) {
360 case I2C_SMBUS_BYTE:
361 case I2C_SMBUS_BYTE_DATA:
362 status = amd_ec_read(smbus, AMD_SMB_DATA, data: &data->byte);
363 if (status)
364 return status;
365 break;
366
367 case I2C_SMBUS_WORD_DATA:
368 case I2C_SMBUS_PROC_CALL:
369 status = amd_ec_read(smbus, AMD_SMB_DATA, data: temp + 0);
370 if (status)
371 return status;
372 status = amd_ec_read(smbus, AMD_SMB_DATA + 1, data: temp + 1);
373 if (status)
374 return status;
375 data->word = (temp[1] << 8) | temp[0];
376 break;
377
378 case I2C_SMBUS_BLOCK_DATA:
379 case I2C_SMBUS_BLOCK_PROC_CALL:
380 status = amd_ec_read(smbus, AMD_SMB_BCNT, data: &len);
381 if (status)
382 return status;
383 len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
384 fallthrough;
385 case I2C_SMBUS_I2C_BLOCK_DATA:
386 for (i = 0; i < len; i++) {
387 status = amd_ec_read(smbus, AMD_SMB_DATA + i,
388 data: data->block + i + 1);
389 if (status)
390 return status;
391 }
392 data->block[0] = len;
393 break;
394 }
395
396 return 0;
397}
398
399
400static u32 amd8111_func(struct i2c_adapter *adapter)
401{
402 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
403 I2C_FUNC_SMBUS_BYTE_DATA |
404 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
405 I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
406 I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC;
407}
408
409static const struct i2c_algorithm smbus_algorithm = {
410 .smbus_xfer = amd8111_access,
411 .functionality = amd8111_func,
412};
413
414
415static const struct pci_device_id amd8111_ids[] = {
416 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
417 { 0, }
418};
419
420MODULE_DEVICE_TABLE (pci, amd8111_ids);
421
422static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
423{
424 struct amd_smbus *smbus;
425 int error;
426
427 if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
428 return -ENODEV;
429
430 smbus = kzalloc(size: sizeof(struct amd_smbus), GFP_KERNEL);
431 if (!smbus)
432 return -ENOMEM;
433
434 smbus->dev = dev;
435 smbus->base = pci_resource_start(dev, 0);
436 smbus->size = pci_resource_len(dev, 0);
437
438 error = acpi_check_resource_conflict(res: &dev->resource[0]);
439 if (error) {
440 error = -ENODEV;
441 goto out_kfree;
442 }
443
444 if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
445 error = -EBUSY;
446 goto out_kfree;
447 }
448
449 smbus->adapter.owner = THIS_MODULE;
450 snprintf(buf: smbus->adapter.name, size: sizeof(smbus->adapter.name),
451 fmt: "SMBus2 AMD8111 adapter at %04x", smbus->base);
452 smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
453 smbus->adapter.algo = &smbus_algorithm;
454 smbus->adapter.algo_data = smbus;
455
456 /* set up the sysfs linkage to our parent device */
457 smbus->adapter.dev.parent = &dev->dev;
458
459 pci_write_config_dword(dev: smbus->dev, AMD_PCI_MISC, val: 0);
460 error = i2c_add_adapter(adap: &smbus->adapter);
461 if (error)
462 goto out_release_region;
463
464 pci_set_drvdata(pdev: dev, data: smbus);
465 return 0;
466
467 out_release_region:
468 release_region(smbus->base, smbus->size);
469 out_kfree:
470 kfree(objp: smbus);
471 return error;
472}
473
474static void amd8111_remove(struct pci_dev *dev)
475{
476 struct amd_smbus *smbus = pci_get_drvdata(pdev: dev);
477
478 i2c_del_adapter(adap: &smbus->adapter);
479 release_region(smbus->base, smbus->size);
480 kfree(objp: smbus);
481}
482
483static struct pci_driver amd8111_driver = {
484 .name = "amd8111_smbus2",
485 .id_table = amd8111_ids,
486 .probe = amd8111_probe,
487 .remove = amd8111_remove,
488};
489
490module_pci_driver(amd8111_driver);
491

source code of linux/drivers/i2c/busses/i2c-amd8111.c