intel_extreme: irq hotplug support for IceLake and newer PCH.

we enable every port interrupt instead of relying on the ports found in the VBT.
ATM only log the plug state when it changes.

Change-Id: I5175fb137d11f0114beb2915a4f363341cfe8e36
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5287
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Jérôme Duval 2022-05-02 20:01:01 +02:00
parent 46bbf334f6
commit 459f1bcd8d
2 changed files with 121 additions and 6 deletions

View File

@ -384,6 +384,21 @@ enum aux_channel {
};
enum hpd_pin {
HPD_PORT_A,
HPD_PORT_B,
HPD_PORT_C,
HPD_PORT_D,
HPD_PORT_E,
HPD_PORT_TC1,
HPD_PORT_TC2,
HPD_PORT_TC3,
HPD_PORT_TC4,
HPD_PORT_TC5,
HPD_PORT_TC6,
};
struct intel_shared_info {
area_id mode_list_area; // area containing display mode list
uint32 mode_count;
@ -716,6 +731,7 @@ struct intel_brightness_legacy {
#define PCH_MASTER_INT_CTL_BDW 0x44200
#define PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(pipe) (1 << (15 + pipe))
#define GEN8_DE_PCH_IRQ (1 << 23)
#define GEN8_DE_PORT_IRQ (1 << 20)
#define PCH_MASTER_INT_CTL_GLOBAL_BDW (1 << 31)
@ -741,17 +757,46 @@ struct intel_brightness_legacy {
#define GEN8_DE_MISC_IER 0x4446c
#define GEN8_DE_EDP_PSR (1 << 19)
#define GEN11_DE_HPD_ISR 0x44470
#define GEN11_DE_HPD_IMR 0x44474
#define GEN11_DE_HPD_IIR 0x44478
#define GEN11_DE_HPD_IER 0x4447c
#define GEN11_DE_TC_HOTPLUG_MASK (0x3f << 16)
#define GEN11_DE_TBT_HOTPLUG_MASK (0x3f)
#define GEN11_TBT_HOTPLUG_CTL 0x44030
#define GEN11_TC_HOTPLUG_CTL 0x44038
#define SHPD_FILTER_CNT 0xc4038
#define SHPD_FILTER_CNT_500_ADJ 0x1d9
#define SDEISR 0xc4000
#define SDEIMR 0xc4004
#define SDEIIR 0xc4008
#define SDEIER 0xc400c
#define SDE_GMBUS_ICP (1 << 23)
#define SHOTPLUG_CTL_DDI 0xc4030
#define SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin) (0x8 << (4 * ((hpd_pin) - HPD_PORT_A)))
#define SHOTPLUG_CTL_TC 0xc4034
#define SHOTPLUG_CTL_TC_HPD_ENABLE(hpd_pin) (0x8 << (4 * ((hpd_pin) - HPD_PORT_TC1)))
#define PCH_PORT_HOTPLUG SHOTPLUG_CTL_DDI
#define PCH_PORT_HOTPLUG2 0xc403c
#define PCH_INTERRUPT_VBLANK_BDW (1 << 0) // GEN8_PIPE_VBLANK
#define GEN8_PIPE_VSYNC (1 << 1)
#define GEN8_PIPE_SCAN_LINE_EVENT (1 << 2)
#define GEN11_DISPLAY_INT_CTL 0x44200 // same as PCH_MASTER_INT_CTL_BDW
#define GEN11_GFX_MSTR_IRQ 0x190010
#define GEN11_MASTER_IRQ (1 << 31)
#define GEN11_DISPLAY_IRQ (1 << 16)
#define GEN11_GT_DW1_IRQ (1 << 1)
#define GEN11_GT_DW0_IRQ (1 << 0)
#define GEN11_DISPLAY_INT_CTL 0x44200 // same as PCH_MASTER_INT_CTL_BDW
#define GEN11_DE_HPD_IRQ (1 << 21)
#define GEN11_GT_INTR_DW0 0x190018
#define GEN11_GT_INTR_DW1 0x19001c
@ -1745,4 +1790,5 @@ struct hardware_status {
uint32 store[1008];
};
#endif /* INTEL_EXTREME_H */

View File

@ -158,15 +158,43 @@ gen8_handle_interrupts(intel_info& info, uint32 interrupt)
interrupt &= ~PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(INTEL_PIPE_C);
}
uint32 iir = 0;
if ((interrupt & GEN8_DE_PORT_IRQ) != 0) {
iir = read32(info, GEN8_DE_PORT_IIR);
uint32 iir = read32(info, GEN8_DE_PORT_IIR);
if (iir != 0) {
write32(info, GEN8_DE_PORT_IIR, iir);
}
interrupt &= ~GEN8_DE_PORT_IRQ;
}
if (info.device_type.Generation() >= 11 && (interrupt & GEN11_DE_HPD_IRQ) != 0) {
dprintf("gen8_handle_interrupts HPD\n");
uint32 iir = read32(info, GEN11_DE_HPD_IIR);
if (iir != 0) {
dprintf("gen8_handle_interrupts HPD_IIR %" B_PRIx32 "\n", iir);
write32(info, GEN11_DE_HPD_IIR, iir);
}
interrupt &= ~GEN11_DE_HPD_IRQ;
}
if ((interrupt & GEN8_DE_PCH_IRQ) != 0) {
dprintf("gen8_handle_interrupts PCH\n");
uint32 iir = read32(info, SDEIIR);
if (iir != 0) {
dprintf("gen8_handle_interrupts PCH_IIR %" B_PRIx32 "\n", iir);
write32(info, SDEIIR, iir);
if (info.shared_info->pch_info >= INTEL_PCH_ICP) {
uint32 ddiHotplug = read32(info, SHOTPLUG_CTL_DDI);
write32(info, SHOTPLUG_CTL_DDI, ddiHotplug);
dprintf("gen8_handle_interrupts PCH_IIR ddiHotplug %" B_PRIx32 "\n", ddiHotplug);
uint32 tcHotplug = read32(info, SHOTPLUG_CTL_TC);
write32(info, SHOTPLUG_CTL_TC, tcHotplug);
dprintf("gen8_handle_interrupts PCH_IIR tcHotplug %" B_PRIx32 "\n", tcHotplug);
}
}
interrupt &= ~GEN8_DE_PCH_IRQ;
}
interrupt &= ~PCH_MASTER_INT_CTL_GLOBAL_BDW;
if (interrupt != 0)
dprintf("gen8_handle_interrupts unhandled %" B_PRIx32 "\n", interrupt);
@ -451,16 +479,23 @@ init_interrupt_handler(intel_info &info)
gen8_enable_global_interrupts(info, true);
if (info.device_type.Generation() >= 11) {
if (info.shared_info->pch_info >= INTEL_PCH_ICP) {
read32(info, SDEIIR);
write32(info, SDEIER, 0xffffffff);
write32(info, SDEIMR, ~SDE_GMBUS_ICP);
read32(info, SDEIMR);
}
uint32 mask = GEN8_AUX_CHANNEL_A;
mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D;
mask |= CNL_AUX_CHANNEL_F;
mask |= ICL_AUX_CHANNEL_E;
read32(info, GEN8_DE_PORT_ISR);
read32(info, GEN8_DE_PORT_IIR);
write32(info, GEN8_DE_PORT_IER, mask);
write32(info, GEN8_DE_PORT_IMR, ~mask);
read32(info, GEN8_DE_PORT_IMR);
read32(info, GEN8_DE_MISC_ISR);
read32(info, GEN8_DE_MISC_IIR);
write32(info, GEN8_DE_MISC_IER, GEN8_DE_EDP_PSR);
write32(info, GEN8_DE_MISC_IMR, ~GEN8_DE_EDP_PSR);
read32(info, GEN8_DE_MISC_IMR);
@ -469,7 +504,41 @@ init_interrupt_handler(intel_info &info)
write32(info, GEN11_GU_MISC_IER, GEN11_GU_MISC_GSE);
write32(info, GEN11_GU_MISC_IMR, ~GEN11_GU_MISC_GSE);
read32(info, GEN11_GU_MISC_IMR);
// Missing: Hotplug
read32(info, GEN11_DE_HPD_IIR);
write32(info, GEN11_DE_HPD_IER,
GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK);
write32(info, GEN11_DE_HPD_IMR, 0xffffffff);
read32(info, GEN11_DE_HPD_IMR);
write32(info, GEN11_TC_HOTPLUG_CTL, 0);
write32(info, GEN11_TBT_HOTPLUG_CTL, 0);
if (info.shared_info->pch_info >= INTEL_PCH_ICP) {
if (info.shared_info->pch_info <= INTEL_PCH_TGP)
write32(info, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
read32(info, SDEIMR);
write32(info, SDEIMR, 0x3f023f07);
read32(info, SDEIMR);
uint32 ctl = read32(info, SHOTPLUG_CTL_DDI);
// we enable everything, should come from the VBT
ctl |= SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A)
| SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B)
| SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C)
| SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D);
write32(info, SHOTPLUG_CTL_DDI, ctl);
ctl = read32(info, SHOTPLUG_CTL_TC);
// we enable everything, should come from the VBT
ctl |= SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC1)
| SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC2)
| SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC3)
| SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC4)
| SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC5)
| SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC6);
write32(info, SHOTPLUG_CTL_TC, ctl);
}
gen11_enable_global_interrupts(info, true);
}
}