xref: /openbmc/linux/drivers/i2c/busses/i2c-amd8111.c (revision 5e77a61f)
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 
19 MODULE_LICENSE("GPL");
20 MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
21 MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
22 
23 struct amd_smbus {
24 	struct pci_dev *dev;
25 	struct i2c_adapter adapter;
26 	int base;
27 	int size;
28 };
29 
30 static 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 
amd_ec_wait_write(struct amd_smbus * smbus)68 static int amd_ec_wait_write(struct amd_smbus *smbus)
69 {
70 	int timeout = 500;
71 
72 	while ((inb(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 
amd_ec_wait_read(struct amd_smbus * smbus)84 static int amd_ec_wait_read(struct amd_smbus *smbus)
85 {
86 	int timeout = 500;
87 
88 	while ((~inb(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 
amd_ec_read(struct amd_smbus * smbus,unsigned char address,unsigned char * data)100 static 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, smbus->base + AMD_EC_CMD);
109 
110 	status = amd_ec_wait_write(smbus);
111 	if (status)
112 		return status;
113 	outb(address, smbus->base + AMD_EC_DATA);
114 
115 	status = amd_ec_wait_read(smbus);
116 	if (status)
117 		return status;
118 	*data = inb(smbus->base + AMD_EC_DATA);
119 
120 	return 0;
121 }
122 
amd_ec_write(struct amd_smbus * smbus,unsigned char address,unsigned char data)123 static 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, smbus->base + AMD_EC_CMD);
132 
133 	status = amd_ec_wait_write(smbus);
134 	if (status)
135 		return status;
136 	outb(address, smbus->base + AMD_EC_DATA);
137 
138 	status = amd_ec_wait_write(smbus);
139 	if (status)
140 		return status;
141 	outb(data, 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 
amd8111_access(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)189 static 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 						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, 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->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, 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->word & 0xff);
237 			if (status)
238 				return status;
239 			status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
240 						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, 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, 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->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, command);
272 		if (status)
273 			return status;
274 		status = amd_ec_write(smbus, AMD_SMB_BCNT, 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->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, command);
290 		if (status)
291 			return status;
292 		status = amd_ec_write(smbus, AMD_SMB_DATA,
293 					data->word & 0xff);
294 		if (status)
295 			return status;
296 		status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
297 					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, command);
308 		if (status)
309 			return status;
310 		status = amd_ec_write(smbus, AMD_SMB_BCNT, 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->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, addr << 1);
329 	if (status)
330 		return status;
331 	status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
332 	if (status)
333 		return status;
334 
335 	status = amd_ec_read(smbus, AMD_SMB_STS, 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, temp + 0);
342 		if (status)
343 			return status;
344 	}
345 
346 	if (~temp[0] & AMD_SMB_STS_DONE) {
347 		msleep(1);
348 		status = amd_ec_read(smbus, AMD_SMB_STS, 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->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, temp + 0);
370 		if (status)
371 			return status;
372 		status = amd_ec_read(smbus, AMD_SMB_DATA + 1, 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, &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->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 
amd8111_func(struct i2c_adapter * adapter)400 static 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 
409 static const struct i2c_algorithm smbus_algorithm = {
410 	.smbus_xfer = amd8111_access,
411 	.functionality = amd8111_func,
412 };
413 
414 
415 static const struct pci_device_id amd8111_ids[] = {
416 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
417 	{ 0, }
418 };
419 
420 MODULE_DEVICE_TABLE (pci, amd8111_ids);
421 
amd8111_probe(struct pci_dev * dev,const struct pci_device_id * id)422 static 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(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(&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(smbus->adapter.name, sizeof(smbus->adapter.name),
451 		"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(smbus->dev, AMD_PCI_MISC, 0);
460 	error = i2c_add_adapter(&smbus->adapter);
461 	if (error)
462 		goto out_release_region;
463 
464 	pci_set_drvdata(dev, smbus);
465 	return 0;
466 
467  out_release_region:
468 	release_region(smbus->base, smbus->size);
469  out_kfree:
470 	kfree(smbus);
471 	return error;
472 }
473 
amd8111_remove(struct pci_dev * dev)474 static void amd8111_remove(struct pci_dev *dev)
475 {
476 	struct amd_smbus *smbus = pci_get_drvdata(dev);
477 
478 	i2c_del_adapter(&smbus->adapter);
479 	release_region(smbus->base, smbus->size);
480 	kfree(smbus);
481 }
482 
483 static struct pci_driver amd8111_driver = {
484 	.name		= "amd8111_smbus2",
485 	.id_table	= amd8111_ids,
486 	.probe		= amd8111_probe,
487 	.remove		= amd8111_remove,
488 };
489 
490 module_pci_driver(amd8111_driver);
491