diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-20 06:32:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-20 06:32:26 -0400 |
commit | eb62722a06c4e6715c71e5c8fcf14aed857c0964 (patch) | |
tree | be931e62515d2f11eac3a9700526fb4c2c3a9349 | |
parent | 03b652e5c0cdbdfe31314b644d2b0bc77e736693 (diff) | |
parent | 883b3b6567bfc8b5da7b3f0cec80513af111d2f5 (diff) |
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang:
"A couple of bugfixes for I2C drivers.
Because the changes for the piix4 driver are larger than usual, the
patches have been in linux-next for more than a week with no reports
coming in. The rest is usual stuff"
* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: omap: Fix error handling for clk_get()
i2c: piix4: Disable completely the IMC during SMBUS_BLOCK_DATA
i2c: piix4: Fix SMBus port selection for AMD Family 17h chips
i2c: imx: fix misleading bus recovery debug message
i2c: imx: use IRQF_SHARED mode to request IRQ
i2c: ismt: Separate I2C block read from SMBus block read
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ismt.c | 5 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 14 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 162 |
4 files changed, 172 insertions, 13 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 54a47b40546f..f96830ffd9f1 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c | |||
@@ -1021,7 +1021,7 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, | |||
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n", | 1023 | dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n", |
1024 | rinfo->sda_gpio, rinfo->scl_gpio); | 1024 | rinfo->scl_gpio, rinfo->sda_gpio); |
1025 | 1025 | ||
1026 | rinfo->prepare_recovery = i2c_imx_prepare_recovery; | 1026 | rinfo->prepare_recovery = i2c_imx_prepare_recovery; |
1027 | rinfo->unprepare_recovery = i2c_imx_unprepare_recovery; | 1027 | rinfo->unprepare_recovery = i2c_imx_unprepare_recovery; |
@@ -1100,7 +1100,7 @@ static int i2c_imx_probe(struct platform_device *pdev) | |||
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | /* Request IRQ */ | 1102 | /* Request IRQ */ |
1103 | ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, | 1103 | ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED, |
1104 | pdev->name, i2c_imx); | 1104 | pdev->name, i2c_imx); |
1105 | if (ret) { | 1105 | if (ret) { |
1106 | dev_err(&pdev->dev, "can't claim irq %d\n", irq); | 1106 | dev_err(&pdev->dev, "can't claim irq %d\n", irq); |
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index 22ffcb73c185..b51adffa4841 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c | |||
@@ -340,12 +340,15 @@ static int ismt_process_desc(const struct ismt_desc *desc, | |||
340 | data->word = dma_buffer[0] | (dma_buffer[1] << 8); | 340 | data->word = dma_buffer[0] | (dma_buffer[1] << 8); |
341 | break; | 341 | break; |
342 | case I2C_SMBUS_BLOCK_DATA: | 342 | case I2C_SMBUS_BLOCK_DATA: |
343 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
344 | if (desc->rxbytes != dma_buffer[0] + 1) | 343 | if (desc->rxbytes != dma_buffer[0] + 1) |
345 | return -EMSGSIZE; | 344 | return -EMSGSIZE; |
346 | 345 | ||
347 | memcpy(data->block, dma_buffer, desc->rxbytes); | 346 | memcpy(data->block, dma_buffer, desc->rxbytes); |
348 | break; | 347 | break; |
348 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
349 | memcpy(&data->block[1], dma_buffer, desc->rxbytes); | ||
350 | data->block[0] = desc->rxbytes; | ||
351 | break; | ||
349 | } | 352 | } |
350 | return 0; | 353 | return 0; |
351 | } | 354 | } |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 1ebb5e947e0b..23c2ea2baedc 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -360,6 +360,7 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) | |||
360 | unsigned long fclk_rate = 12000000; | 360 | unsigned long fclk_rate = 12000000; |
361 | unsigned long internal_clk = 0; | 361 | unsigned long internal_clk = 0; |
362 | struct clk *fclk; | 362 | struct clk *fclk; |
363 | int error; | ||
363 | 364 | ||
364 | if (omap->rev >= OMAP_I2C_REV_ON_3430_3530) { | 365 | if (omap->rev >= OMAP_I2C_REV_ON_3430_3530) { |
365 | /* | 366 | /* |
@@ -378,6 +379,13 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) | |||
378 | * do this bit unconditionally. | 379 | * do this bit unconditionally. |
379 | */ | 380 | */ |
380 | fclk = clk_get(omap->dev, "fck"); | 381 | fclk = clk_get(omap->dev, "fck"); |
382 | if (IS_ERR(fclk)) { | ||
383 | error = PTR_ERR(fclk); | ||
384 | dev_err(omap->dev, "could not get fck: %i\n", error); | ||
385 | |||
386 | return error; | ||
387 | } | ||
388 | |||
381 | fclk_rate = clk_get_rate(fclk); | 389 | fclk_rate = clk_get_rate(fclk); |
382 | clk_put(fclk); | 390 | clk_put(fclk); |
383 | 391 | ||
@@ -410,6 +418,12 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) | |||
410 | else | 418 | else |
411 | internal_clk = 4000; | 419 | internal_clk = 4000; |
412 | fclk = clk_get(omap->dev, "fck"); | 420 | fclk = clk_get(omap->dev, "fck"); |
421 | if (IS_ERR(fclk)) { | ||
422 | error = PTR_ERR(fclk); | ||
423 | dev_err(omap->dev, "could not get fck: %i\n", error); | ||
424 | |||
425 | return error; | ||
426 | } | ||
413 | fclk_rate = clk_get_rate(fclk) / 1000; | 427 | fclk_rate = clk_get_rate(fclk) / 1000; |
414 | clk_put(fclk); | 428 | clk_put(fclk); |
415 | 429 | ||
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 0ecdb47a23ab..174579d32e5f 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c | |||
@@ -85,6 +85,9 @@ | |||
85 | /* SB800 constants */ | 85 | /* SB800 constants */ |
86 | #define SB800_PIIX4_SMB_IDX 0xcd6 | 86 | #define SB800_PIIX4_SMB_IDX 0xcd6 |
87 | 87 | ||
88 | #define KERNCZ_IMC_IDX 0x3e | ||
89 | #define KERNCZ_IMC_DATA 0x3f | ||
90 | |||
88 | /* | 91 | /* |
89 | * SB800 port is selected by bits 2:1 of the smb_en register (0x2c) | 92 | * SB800 port is selected by bits 2:1 of the smb_en register (0x2c) |
90 | * or the smb_sel register (0x2e), depending on bit 0 of register 0x2f. | 93 | * or the smb_sel register (0x2e), depending on bit 0 of register 0x2f. |
@@ -94,6 +97,12 @@ | |||
94 | #define SB800_PIIX4_PORT_IDX_ALT 0x2e | 97 | #define SB800_PIIX4_PORT_IDX_ALT 0x2e |
95 | #define SB800_PIIX4_PORT_IDX_SEL 0x2f | 98 | #define SB800_PIIX4_PORT_IDX_SEL 0x2f |
96 | #define SB800_PIIX4_PORT_IDX_MASK 0x06 | 99 | #define SB800_PIIX4_PORT_IDX_MASK 0x06 |
100 | #define SB800_PIIX4_PORT_IDX_SHIFT 1 | ||
101 | |||
102 | /* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ | ||
103 | #define SB800_PIIX4_PORT_IDX_KERNCZ 0x02 | ||
104 | #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18 | ||
105 | #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3 | ||
97 | 106 | ||
98 | /* insmod parameters */ | 107 | /* insmod parameters */ |
99 | 108 | ||
@@ -149,6 +158,8 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { | |||
149 | */ | 158 | */ |
150 | static DEFINE_MUTEX(piix4_mutex_sb800); | 159 | static DEFINE_MUTEX(piix4_mutex_sb800); |
151 | static u8 piix4_port_sel_sb800; | 160 | static u8 piix4_port_sel_sb800; |
161 | static u8 piix4_port_mask_sb800; | ||
162 | static u8 piix4_port_shift_sb800; | ||
152 | static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { | 163 | static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { |
153 | " port 0", " port 2", " port 3", " port 4" | 164 | " port 0", " port 2", " port 3", " port 4" |
154 | }; | 165 | }; |
@@ -159,6 +170,7 @@ struct i2c_piix4_adapdata { | |||
159 | 170 | ||
160 | /* SB800 */ | 171 | /* SB800 */ |
161 | bool sb800_main; | 172 | bool sb800_main; |
173 | bool notify_imc; | ||
162 | u8 port; /* Port number, shifted */ | 174 | u8 port; /* Port number, shifted */ |
163 | }; | 175 | }; |
164 | 176 | ||
@@ -347,7 +359,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, | |||
347 | 359 | ||
348 | /* Find which register is used for port selection */ | 360 | /* Find which register is used for port selection */ |
349 | if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) { | 361 | if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) { |
350 | piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; | 362 | switch (PIIX4_dev->device) { |
363 | case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS: | ||
364 | piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ; | ||
365 | piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ; | ||
366 | piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ; | ||
367 | break; | ||
368 | case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS: | ||
369 | default: | ||
370 | piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; | ||
371 | piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; | ||
372 | piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; | ||
373 | break; | ||
374 | } | ||
351 | } else { | 375 | } else { |
352 | mutex_lock(&piix4_mutex_sb800); | 376 | mutex_lock(&piix4_mutex_sb800); |
353 | outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); | 377 | outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); |
@@ -355,6 +379,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, | |||
355 | piix4_port_sel_sb800 = (port_sel & 0x01) ? | 379 | piix4_port_sel_sb800 = (port_sel & 0x01) ? |
356 | SB800_PIIX4_PORT_IDX_ALT : | 380 | SB800_PIIX4_PORT_IDX_ALT : |
357 | SB800_PIIX4_PORT_IDX; | 381 | SB800_PIIX4_PORT_IDX; |
382 | piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; | ||
383 | piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; | ||
358 | mutex_unlock(&piix4_mutex_sb800); | 384 | mutex_unlock(&piix4_mutex_sb800); |
359 | } | 385 | } |
360 | 386 | ||
@@ -572,6 +598,67 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, | |||
572 | return 0; | 598 | return 0; |
573 | } | 599 | } |
574 | 600 | ||
601 | static uint8_t piix4_imc_read(uint8_t idx) | ||
602 | { | ||
603 | outb_p(idx, KERNCZ_IMC_IDX); | ||
604 | return inb_p(KERNCZ_IMC_DATA); | ||
605 | } | ||
606 | |||
607 | static void piix4_imc_write(uint8_t idx, uint8_t value) | ||
608 | { | ||
609 | outb_p(idx, KERNCZ_IMC_IDX); | ||
610 | outb_p(value, KERNCZ_IMC_DATA); | ||
611 | } | ||
612 | |||
613 | static int piix4_imc_sleep(void) | ||
614 | { | ||
615 | int timeout = MAX_TIMEOUT; | ||
616 | |||
617 | if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc")) | ||
618 | return -EBUSY; | ||
619 | |||
620 | /* clear response register */ | ||
621 | piix4_imc_write(0x82, 0x00); | ||
622 | /* request ownership flag */ | ||
623 | piix4_imc_write(0x83, 0xB4); | ||
624 | /* kick off IMC Mailbox command 96 */ | ||
625 | piix4_imc_write(0x80, 0x96); | ||
626 | |||
627 | while (timeout--) { | ||
628 | if (piix4_imc_read(0x82) == 0xfa) { | ||
629 | release_region(KERNCZ_IMC_IDX, 2); | ||
630 | return 0; | ||
631 | } | ||
632 | usleep_range(1000, 2000); | ||
633 | } | ||
634 | |||
635 | release_region(KERNCZ_IMC_IDX, 2); | ||
636 | return -ETIMEDOUT; | ||
637 | } | ||
638 | |||
639 | static void piix4_imc_wakeup(void) | ||
640 | { | ||
641 | int timeout = MAX_TIMEOUT; | ||
642 | |||
643 | if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc")) | ||
644 | return; | ||
645 | |||
646 | /* clear response register */ | ||
647 | piix4_imc_write(0x82, 0x00); | ||
648 | /* release ownership flag */ | ||
649 | piix4_imc_write(0x83, 0xB5); | ||
650 | /* kick off IMC Mailbox command 96 */ | ||
651 | piix4_imc_write(0x80, 0x96); | ||
652 | |||
653 | while (timeout--) { | ||
654 | if (piix4_imc_read(0x82) == 0xfa) | ||
655 | break; | ||
656 | usleep_range(1000, 2000); | ||
657 | } | ||
658 | |||
659 | release_region(KERNCZ_IMC_IDX, 2); | ||
660 | } | ||
661 | |||
575 | /* | 662 | /* |
576 | * Handles access to multiple SMBus ports on the SB800. | 663 | * Handles access to multiple SMBus ports on the SB800. |
577 | * The port is selected by bits 2:1 of the smb_en register (0x2c). | 664 | * The port is selected by bits 2:1 of the smb_en register (0x2c). |
@@ -612,12 +699,47 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, | |||
612 | return -EBUSY; | 699 | return -EBUSY; |
613 | } | 700 | } |
614 | 701 | ||
702 | /* | ||
703 | * Notify the IMC (Integrated Micro Controller) if required. | ||
704 | * Among other responsibilities, the IMC is in charge of monitoring | ||
705 | * the System fans and temperature sensors, and act accordingly. | ||
706 | * All this is done through SMBus and can/will collide | ||
707 | * with our transactions if they are long (BLOCK_DATA). | ||
708 | * Therefore we need to request the ownership flag during those | ||
709 | * transactions. | ||
710 | */ | ||
711 | if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) { | ||
712 | int ret; | ||
713 | |||
714 | ret = piix4_imc_sleep(); | ||
715 | switch (ret) { | ||
716 | case -EBUSY: | ||
717 | dev_warn(&adap->dev, | ||
718 | "IMC base address index region 0x%x already in use.\n", | ||
719 | KERNCZ_IMC_IDX); | ||
720 | break; | ||
721 | case -ETIMEDOUT: | ||
722 | dev_warn(&adap->dev, | ||
723 | "Failed to communicate with the IMC.\n"); | ||
724 | break; | ||
725 | default: | ||
726 | break; | ||
727 | } | ||
728 | |||
729 | /* If IMC communication fails do not retry */ | ||
730 | if (ret) { | ||
731 | dev_warn(&adap->dev, | ||
732 | "Continuing without IMC notification.\n"); | ||
733 | adapdata->notify_imc = false; | ||
734 | } | ||
735 | } | ||
736 | |||
615 | outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX); | 737 | outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX); |
616 | smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); | 738 | smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); |
617 | 739 | ||
618 | port = adapdata->port; | 740 | port = adapdata->port; |
619 | if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != port) | 741 | if ((smba_en_lo & piix4_port_mask_sb800) != port) |
620 | outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | port, | 742 | outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port, |
621 | SB800_PIIX4_SMB_IDX + 1); | 743 | SB800_PIIX4_SMB_IDX + 1); |
622 | 744 | ||
623 | retval = piix4_access(adap, addr, flags, read_write, | 745 | retval = piix4_access(adap, addr, flags, read_write, |
@@ -628,6 +750,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, | |||
628 | /* Release the semaphore */ | 750 | /* Release the semaphore */ |
629 | outb_p(smbslvcnt | 0x20, SMBSLVCNT); | 751 | outb_p(smbslvcnt | 0x20, SMBSLVCNT); |
630 | 752 | ||
753 | if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) | ||
754 | piix4_imc_wakeup(); | ||
755 | |||
631 | mutex_unlock(&piix4_mutex_sb800); | 756 | mutex_unlock(&piix4_mutex_sb800); |
632 | 757 | ||
633 | return retval; | 758 | return retval; |
@@ -679,7 +804,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS]; | |||
679 | static struct i2c_adapter *piix4_aux_adapter; | 804 | static struct i2c_adapter *piix4_aux_adapter; |
680 | 805 | ||
681 | static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, | 806 | static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, |
682 | bool sb800_main, u8 port, | 807 | bool sb800_main, u8 port, bool notify_imc, |
683 | const char *name, struct i2c_adapter **padap) | 808 | const char *name, struct i2c_adapter **padap) |
684 | { | 809 | { |
685 | struct i2c_adapter *adap; | 810 | struct i2c_adapter *adap; |
@@ -706,7 +831,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, | |||
706 | 831 | ||
707 | adapdata->smba = smba; | 832 | adapdata->smba = smba; |
708 | adapdata->sb800_main = sb800_main; | 833 | adapdata->sb800_main = sb800_main; |
709 | adapdata->port = port << 1; | 834 | adapdata->port = port << piix4_port_shift_sb800; |
835 | adapdata->notify_imc = notify_imc; | ||
710 | 836 | ||
711 | /* set up the sysfs linkage to our parent device */ | 837 | /* set up the sysfs linkage to our parent device */ |
712 | adap->dev.parent = &dev->dev; | 838 | adap->dev.parent = &dev->dev; |
@@ -728,14 +854,15 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, | |||
728 | return 0; | 854 | return 0; |
729 | } | 855 | } |
730 | 856 | ||
731 | static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) | 857 | static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba, |
858 | bool notify_imc) | ||
732 | { | 859 | { |
733 | struct i2c_piix4_adapdata *adapdata; | 860 | struct i2c_piix4_adapdata *adapdata; |
734 | int port; | 861 | int port; |
735 | int retval; | 862 | int retval; |
736 | 863 | ||
737 | for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { | 864 | for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { |
738 | retval = piix4_add_adapter(dev, smba, true, port, | 865 | retval = piix4_add_adapter(dev, smba, true, port, notify_imc, |
739 | piix4_main_port_names_sb800[port], | 866 | piix4_main_port_names_sb800[port], |
740 | &piix4_main_adapters[port]); | 867 | &piix4_main_adapters[port]); |
741 | if (retval < 0) | 868 | if (retval < 0) |
@@ -769,6 +896,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
769 | dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && | 896 | dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && |
770 | dev->revision >= 0x40) || | 897 | dev->revision >= 0x40) || |
771 | dev->vendor == PCI_VENDOR_ID_AMD) { | 898 | dev->vendor == PCI_VENDOR_ID_AMD) { |
899 | bool notify_imc = false; | ||
772 | is_sb800 = true; | 900 | is_sb800 = true; |
773 | 901 | ||
774 | if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) { | 902 | if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) { |
@@ -778,6 +906,20 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
778 | return -EBUSY; | 906 | return -EBUSY; |
779 | } | 907 | } |
780 | 908 | ||
909 | if (dev->vendor == PCI_VENDOR_ID_AMD && | ||
910 | dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) { | ||
911 | u8 imc; | ||
912 | |||
913 | /* | ||
914 | * Detect if IMC is active or not, this method is | ||
915 | * described on coreboot's AMD IMC notes | ||
916 | */ | ||
917 | pci_bus_read_config_byte(dev->bus, PCI_DEVFN(0x14, 3), | ||
918 | 0x40, &imc); | ||
919 | if (imc & 0x80) | ||
920 | notify_imc = true; | ||
921 | } | ||
922 | |||
781 | /* base address location etc changed in SB800 */ | 923 | /* base address location etc changed in SB800 */ |
782 | retval = piix4_setup_sb800(dev, id, 0); | 924 | retval = piix4_setup_sb800(dev, id, 0); |
783 | if (retval < 0) { | 925 | if (retval < 0) { |
@@ -789,7 +931,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
789 | * Try to register multiplexed main SMBus adapter, | 931 | * Try to register multiplexed main SMBus adapter, |
790 | * give up if we can't | 932 | * give up if we can't |
791 | */ | 933 | */ |
792 | retval = piix4_add_adapters_sb800(dev, retval); | 934 | retval = piix4_add_adapters_sb800(dev, retval, notify_imc); |
793 | if (retval < 0) { | 935 | if (retval < 0) { |
794 | release_region(SB800_PIIX4_SMB_IDX, 2); | 936 | release_region(SB800_PIIX4_SMB_IDX, 2); |
795 | return retval; | 937 | return retval; |
@@ -800,7 +942,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
800 | return retval; | 942 | return retval; |
801 | 943 | ||
802 | /* Try to register main SMBus adapter, give up if we can't */ | 944 | /* Try to register main SMBus adapter, give up if we can't */ |
803 | retval = piix4_add_adapter(dev, retval, false, 0, "", | 945 | retval = piix4_add_adapter(dev, retval, false, 0, false, "", |
804 | &piix4_main_adapters[0]); | 946 | &piix4_main_adapters[0]); |
805 | if (retval < 0) | 947 | if (retval < 0) |
806 | return retval; | 948 | return retval; |
@@ -827,7 +969,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
827 | if (retval > 0) { | 969 | if (retval > 0) { |
828 | /* Try to add the aux adapter if it exists, | 970 | /* Try to add the aux adapter if it exists, |
829 | * piix4_add_adapter will clean up if this fails */ | 971 | * piix4_add_adapter will clean up if this fails */ |
830 | piix4_add_adapter(dev, retval, false, 0, | 972 | piix4_add_adapter(dev, retval, false, 0, false, |
831 | is_sb800 ? piix4_aux_port_name_sb800 : "", | 973 | is_sb800 ? piix4_aux_port_name_sb800 : "", |
832 | &piix4_aux_adapter); | 974 | &piix4_aux_adapter); |
833 | } | 975 | } |