i2c-amd756.c (10651B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> 4 5 Shamelessly ripped from i2c-piix4.c: 6 7 Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and 8 Philip Edelbrock <phil@netroedge.com> 9 10*/ 11 12/* 13 2002-04-08: Added nForce support. (Csaba Halasz) 14 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil) 15 2002-12-28: Rewritten into something that resembles a Linux driver (hch) 16 2003-11-29: Added back AMD8111 removed by the previous rewrite. 17 (Philip Pokorny) 18*/ 19 20/* 21 Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce 22 Note: we assume there can only be one device, with one SMBus interface. 23*/ 24 25#include <linux/module.h> 26#include <linux/pci.h> 27#include <linux/kernel.h> 28#include <linux/delay.h> 29#include <linux/stddef.h> 30#include <linux/ioport.h> 31#include <linux/i2c.h> 32#include <linux/acpi.h> 33#include <linux/io.h> 34 35/* AMD756 SMBus address offsets */ 36#define SMB_ADDR_OFFSET 0xE0 37#define SMB_IOSIZE 16 38#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) 39#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) 40#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) 41#define SMB_HOST_DATA (0x6 + amd756_ioport) 42#define SMB_HOST_COMMAND (0x8 + amd756_ioport) 43#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) 44#define SMB_HAS_DATA (0xA + amd756_ioport) 45#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) 46#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) 47#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) 48 49/* PCI Address Constants */ 50 51/* address of I/O space */ 52#define SMBBA 0x058 /* mh */ 53#define SMBBANFORCE 0x014 54 55/* general configuration */ 56#define SMBGCFG 0x041 /* mh */ 57 58/* silicon revision code */ 59#define SMBREV 0x008 60 61/* Other settings */ 62#define MAX_TIMEOUT 500 63 64/* AMD756 constants */ 65#define AMD756_QUICK 0x00 66#define AMD756_BYTE 0x01 67#define AMD756_BYTE_DATA 0x02 68#define AMD756_WORD_DATA 0x03 69#define AMD756_PROCESS_CALL 0x04 70#define AMD756_BLOCK_DATA 0x05 71 72static struct pci_driver amd756_driver; 73static unsigned short amd756_ioport; 74 75/* 76 SMBUS event = I/O 28-29 bit 11 77 see E0 for the status bits and enabled in E2 78 79*/ 80#define GS_ABRT_STS (1 << 0) 81#define GS_COL_STS (1 << 1) 82#define GS_PRERR_STS (1 << 2) 83#define GS_HST_STS (1 << 3) 84#define GS_HCYC_STS (1 << 4) 85#define GS_TO_STS (1 << 5) 86#define GS_SMB_STS (1 << 11) 87 88#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ 89 GS_HCYC_STS | GS_TO_STS ) 90 91#define GE_CYC_TYPE_MASK (7) 92#define GE_HOST_STC (1 << 3) 93#define GE_ABORT (1 << 5) 94 95 96static int amd756_transaction(struct i2c_adapter *adap) 97{ 98 int temp; 99 int result = 0; 100 int timeout = 0; 101 102 dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " 103 "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), 104 inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), 105 inb_p(SMB_HOST_DATA)); 106 107 /* Make sure the SMBus host is ready to start transmitting */ 108 if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { 109 dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp); 110 do { 111 msleep(1); 112 temp = inw_p(SMB_GLOBAL_STATUS); 113 } while ((temp & (GS_HST_STS | GS_SMB_STS)) && 114 (timeout++ < MAX_TIMEOUT)); 115 /* If the SMBus is still busy, we give up */ 116 if (timeout > MAX_TIMEOUT) { 117 dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp); 118 goto abort; 119 } 120 timeout = 0; 121 } 122 123 /* start the transaction by setting the start bit */ 124 outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE); 125 126 /* We will always wait for a fraction of a second! */ 127 do { 128 msleep(1); 129 temp = inw_p(SMB_GLOBAL_STATUS); 130 } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)); 131 132 /* If the SMBus is still busy, we give up */ 133 if (timeout > MAX_TIMEOUT) { 134 dev_dbg(&adap->dev, "Completion timeout!\n"); 135 goto abort; 136 } 137 138 if (temp & GS_PRERR_STS) { 139 result = -ENXIO; 140 dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); 141 } 142 143 if (temp & GS_COL_STS) { 144 result = -EIO; 145 dev_warn(&adap->dev, "SMBus collision!\n"); 146 } 147 148 if (temp & GS_TO_STS) { 149 result = -ETIMEDOUT; 150 dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); 151 } 152 153 if (temp & GS_HCYC_STS) 154 dev_dbg(&adap->dev, "SMBus protocol success!\n"); 155 156 outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); 157 158#ifdef DEBUG 159 if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { 160 dev_dbg(&adap->dev, 161 "Failed reset at end of transaction (%04x)\n", temp); 162 } 163#endif 164 165 dev_dbg(&adap->dev, 166 "Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", 167 inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), 168 inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); 169 170 return result; 171 172 abort: 173 dev_warn(&adap->dev, "Sending abort\n"); 174 outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); 175 msleep(100); 176 outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); 177 return -EIO; 178} 179 180/* Return negative errno on error. */ 181static s32 amd756_access(struct i2c_adapter * adap, u16 addr, 182 unsigned short flags, char read_write, 183 u8 command, int size, union i2c_smbus_data * data) 184{ 185 int i, len; 186 int status; 187 188 switch (size) { 189 case I2C_SMBUS_QUICK: 190 outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), 191 SMB_HOST_ADDRESS); 192 size = AMD756_QUICK; 193 break; 194 case I2C_SMBUS_BYTE: 195 outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), 196 SMB_HOST_ADDRESS); 197 if (read_write == I2C_SMBUS_WRITE) 198 outb_p(command, SMB_HOST_DATA); 199 size = AMD756_BYTE; 200 break; 201 case I2C_SMBUS_BYTE_DATA: 202 outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), 203 SMB_HOST_ADDRESS); 204 outb_p(command, SMB_HOST_COMMAND); 205 if (read_write == I2C_SMBUS_WRITE) 206 outw_p(data->byte, SMB_HOST_DATA); 207 size = AMD756_BYTE_DATA; 208 break; 209 case I2C_SMBUS_WORD_DATA: 210 outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), 211 SMB_HOST_ADDRESS); 212 outb_p(command, SMB_HOST_COMMAND); 213 if (read_write == I2C_SMBUS_WRITE) 214 outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ 215 size = AMD756_WORD_DATA; 216 break; 217 case I2C_SMBUS_BLOCK_DATA: 218 outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), 219 SMB_HOST_ADDRESS); 220 outb_p(command, SMB_HOST_COMMAND); 221 if (read_write == I2C_SMBUS_WRITE) { 222 len = data->block[0]; 223 if (len < 0) 224 len = 0; 225 if (len > 32) 226 len = 32; 227 outw_p(len, SMB_HOST_DATA); 228 /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ 229 for (i = 1; i <= len; i++) 230 outb_p(data->block[i], 231 SMB_HOST_BLOCK_DATA); 232 } 233 size = AMD756_BLOCK_DATA; 234 break; 235 default: 236 dev_warn(&adap->dev, "Unsupported transaction %d\n", size); 237 return -EOPNOTSUPP; 238 } 239 240 /* How about enabling interrupts... */ 241 outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); 242 243 status = amd756_transaction(adap); 244 if (status) 245 return status; 246 247 if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) 248 return 0; 249 250 251 switch (size) { 252 case AMD756_BYTE: 253 data->byte = inw_p(SMB_HOST_DATA); 254 break; 255 case AMD756_BYTE_DATA: 256 data->byte = inw_p(SMB_HOST_DATA); 257 break; 258 case AMD756_WORD_DATA: 259 data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ 260 break; 261 case AMD756_BLOCK_DATA: 262 data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f; 263 if(data->block[0] > 32) 264 data->block[0] = 32; 265 /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ 266 for (i = 1; i <= data->block[0]; i++) 267 data->block[i] = inb_p(SMB_HOST_BLOCK_DATA); 268 break; 269 } 270 271 return 0; 272} 273 274static u32 amd756_func(struct i2c_adapter *adapter) 275{ 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 const struct i2c_algorithm smbus_algorithm = { 282 .smbus_xfer = amd756_access, 283 .functionality = amd756_func, 284}; 285 286struct i2c_adapter amd756_smbus = { 287 .owner = THIS_MODULE, 288 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, 289 .algo = &smbus_algorithm, 290}; 291 292enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 }; 293static const char* chipname[] = { 294 "AMD756", "AMD766", "AMD768", 295 "nVidia nForce", "AMD8111", 296}; 297 298static const struct pci_device_id amd756_ids[] = { 299 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), 300 .driver_data = AMD756 }, 301 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), 302 .driver_data = AMD766 }, 303 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443), 304 .driver_data = AMD768 }, 305 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 306 .driver_data = AMD8111 }, 307 { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS), 308 .driver_data = NFORCE }, 309 { 0, } 310}; 311 312MODULE_DEVICE_TABLE (pci, amd756_ids); 313 314static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id) 315{ 316 int nforce = (id->driver_data == NFORCE); 317 int error; 318 u8 temp; 319 320 if (amd756_ioport) { 321 dev_err(&pdev->dev, "Only one device supported " 322 "(you have a strange motherboard, btw)\n"); 323 return -ENODEV; 324 } 325 326 if (nforce) { 327 if (PCI_FUNC(pdev->devfn) != 1) 328 return -ENODEV; 329 330 pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport); 331 amd756_ioport &= 0xfffc; 332 } else { /* amd */ 333 if (PCI_FUNC(pdev->devfn) != 3) 334 return -ENODEV; 335 336 pci_read_config_byte(pdev, SMBGCFG, &temp); 337 if ((temp & 128) == 0) { 338 dev_err(&pdev->dev, 339 "Error: SMBus controller I/O not enabled!\n"); 340 return -ENODEV; 341 } 342 343 /* Determine the address of the SMBus areas */ 344 /* Technically it is a dword but... */ 345 pci_read_config_word(pdev, SMBBA, &amd756_ioport); 346 amd756_ioport &= 0xff00; 347 amd756_ioport += SMB_ADDR_OFFSET; 348 } 349 350 error = acpi_check_region(amd756_ioport, SMB_IOSIZE, 351 amd756_driver.name); 352 if (error) 353 return -ENODEV; 354 355 if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { 356 dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", 357 amd756_ioport); 358 return -ENODEV; 359 } 360 361 pci_read_config_byte(pdev, SMBREV, &temp); 362 dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); 363 dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport); 364 365 /* set up the sysfs linkage to our parent device */ 366 amd756_smbus.dev.parent = &pdev->dev; 367 368 snprintf(amd756_smbus.name, sizeof(amd756_smbus.name), 369 "SMBus %s adapter at %04x", chipname[id->driver_data], 370 amd756_ioport); 371 372 error = i2c_add_adapter(&amd756_smbus); 373 if (error) 374 goto out_err; 375 376 return 0; 377 378 out_err: 379 release_region(amd756_ioport, SMB_IOSIZE); 380 return error; 381} 382 383static void amd756_remove(struct pci_dev *dev) 384{ 385 i2c_del_adapter(&amd756_smbus); 386 release_region(amd756_ioport, SMB_IOSIZE); 387} 388 389static struct pci_driver amd756_driver = { 390 .name = "amd756_smbus", 391 .id_table = amd756_ids, 392 .probe = amd756_probe, 393 .remove = amd756_remove, 394}; 395 396module_pci_driver(amd756_driver); 397 398MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>"); 399MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver"); 400MODULE_LICENSE("GPL"); 401 402EXPORT_SYMBOL(amd756_smbus);