aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2017-07-15 19:51:26 -0400
committerWolfram Sang <wsa@the-dreams.de>2017-10-13 15:05:55 -0400
commit0fe16195f89173652cf111d7b384941b00c5aabd (patch)
tree8c867d9c6003a6e67fd2cf7c72d861ea0c7abe0a
parenteba523b468a1e30384b6e8c1a9419163f325086e (diff)
i2c: piix4: Fix SMBus port selection for AMD Family 17h chips
AMD Family 17h uses the KERNCZ SMBus controller. While its documentation is not publicly available, it is documented in the BIOS and Kernel Developer’s Guide for AMD Family 15h Models 60h-6Fh Processors. On this SMBus controller, the port select register is at PMx register 0x02, bit 4:3 (PMx00 register bit 20:19). Without this patch, the 4 SMBus channels on AMD Family 17h chips are mirrored and report the same chips on all channels. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Jean Delvare <jdelvare@suse.de> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Cc: stable@kernel.org
-rw-r--r--drivers/i2c/busses/i2c-piix4.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 0ecdb47a23ab..01f767ee4546 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -94,6 +94,12 @@
94#define SB800_PIIX4_PORT_IDX_ALT 0x2e 94#define SB800_PIIX4_PORT_IDX_ALT 0x2e
95#define SB800_PIIX4_PORT_IDX_SEL 0x2f 95#define SB800_PIIX4_PORT_IDX_SEL 0x2f
96#define SB800_PIIX4_PORT_IDX_MASK 0x06 96#define SB800_PIIX4_PORT_IDX_MASK 0x06
97#define SB800_PIIX4_PORT_IDX_SHIFT 1
98
99/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
100#define SB800_PIIX4_PORT_IDX_KERNCZ 0x02
101#define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18
102#define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3
97 103
98/* insmod parameters */ 104/* insmod parameters */
99 105
@@ -149,6 +155,8 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
149 */ 155 */
150static DEFINE_MUTEX(piix4_mutex_sb800); 156static DEFINE_MUTEX(piix4_mutex_sb800);
151static u8 piix4_port_sel_sb800; 157static u8 piix4_port_sel_sb800;
158static u8 piix4_port_mask_sb800;
159static u8 piix4_port_shift_sb800;
152static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { 160static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
153 " port 0", " port 2", " port 3", " port 4" 161 " port 0", " port 2", " port 3", " port 4"
154}; 162};
@@ -347,7 +355,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
347 355
348 /* Find which register is used for port selection */ 356 /* Find which register is used for port selection */
349 if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) { 357 if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) {
350 piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; 358 switch (PIIX4_dev->device) {
359 case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS:
360 piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ;
361 piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ;
362 piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ;
363 break;
364 case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS:
365 default:
366 piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
367 piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
368 piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
369 break;
370 }
351 } else { 371 } else {
352 mutex_lock(&piix4_mutex_sb800); 372 mutex_lock(&piix4_mutex_sb800);
353 outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); 373 outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
@@ -355,6 +375,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
355 piix4_port_sel_sb800 = (port_sel & 0x01) ? 375 piix4_port_sel_sb800 = (port_sel & 0x01) ?
356 SB800_PIIX4_PORT_IDX_ALT : 376 SB800_PIIX4_PORT_IDX_ALT :
357 SB800_PIIX4_PORT_IDX; 377 SB800_PIIX4_PORT_IDX;
378 piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
379 piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
358 mutex_unlock(&piix4_mutex_sb800); 380 mutex_unlock(&piix4_mutex_sb800);
359 } 381 }
360 382
@@ -616,8 +638,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
616 smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); 638 smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
617 639
618 port = adapdata->port; 640 port = adapdata->port;
619 if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != port) 641 if ((smba_en_lo & piix4_port_mask_sb800) != port)
620 outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | port, 642 outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port,
621 SB800_PIIX4_SMB_IDX + 1); 643 SB800_PIIX4_SMB_IDX + 1);
622 644
623 retval = piix4_access(adap, addr, flags, read_write, 645 retval = piix4_access(adap, addr, flags, read_write,
@@ -706,7 +728,7 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
706 728
707 adapdata->smba = smba; 729 adapdata->smba = smba;
708 adapdata->sb800_main = sb800_main; 730 adapdata->sb800_main = sb800_main;
709 adapdata->port = port << 1; 731 adapdata->port = port << piix4_port_shift_sb800;
710 732
711 /* set up the sysfs linkage to our parent device */ 733 /* set up the sysfs linkage to our parent device */
712 adap->dev.parent = &dev->dev; 734 adap->dev.parent = &dev->dev;