The pattern of a power well backing a set of fuses whose initialization we need to wait for during power well enabling is common to all GEN9+ platforms. Adding support for this to the HSW power well enable helper allows us to use the HSW/BDW power well code for GEN9+ as well in a follow-up patch. Signed-off-by: Imre Deak <imre.deak@xxxxxxxxx> --- drivers/gpu/drm/i915/gvt/display.c | 6 +++--- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 8 ++++---- drivers/gpu/drm/i915/intel_runtime_pm.c | 34 ++++++++++++++++++++++++++------- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 2deb05f..13599bb 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -178,9 +178,9 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) SDE_PORTE_HOTPLUG_SPT); vgpu_vreg(vgpu, SKL_FUSE_STATUS) |= SKL_FUSE_DOWNLOAD_STATUS | - SKL_FUSE_PG0_DIST_STATUS | - SKL_FUSE_PG1_DIST_STATUS | - SKL_FUSE_PG2_DIST_STATUS; + SKL_FUSE_PG_DIST_STATUS(0) | + SKL_FUSE_PG_DIST_STATUS(1) | + SKL_FUSE_PG_DIST_STATUS(2); vgpu_vreg(vgpu, LCPLL1_CTL) |= LCPLL_PLL_ENABLE | LCPLL_PLL_LOCK; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dc5ca5a..9e97536 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1396,6 +1396,7 @@ struct i915_power_well { u32 irq_pipe_mask; /* The pw is backing the VGA functionality */ bool has_vga:1; + bool has_fuses:1; } hsw; }; const struct i915_power_well_ops *ops; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 845f50c..794d65c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8023,10 +8023,10 @@ enum { /* SKL Fuse Status */ #define SKL_FUSE_STATUS _MMIO(0x42000) -#define SKL_FUSE_DOWNLOAD_STATUS (1<<31) -#define SKL_FUSE_PG0_DIST_STATUS (1<<27) -#define SKL_FUSE_PG1_DIST_STATUS (1<<26) -#define SKL_FUSE_PG2_DIST_STATUS (1<<25) +#define SKL_FUSE_DOWNLOAD_STATUS (1<<31) +/* PG0 (HW control->no power well ID), PG1..PG2 (SKL_DISP_PW1..SKL_DISP_PW2) */ +#define SKL_PW_TO_PG(pw) ((pw) - SKL_DISP_PW_1 + 1) +#define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - (pg))) /* Per-pipe DDI Function Control */ #define _TRANS_DDI_FUNC_CTL_A 0x60400 diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 14d4ff4..c204be0 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -400,16 +400,36 @@ static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8)); } +static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, + int pg) +{ + /* Timeout 5us for PG#0, for other PGs 1us */ + WARN_ON(intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, + SKL_FUSE_PG_DIST_STATUS(pg), + SKL_FUSE_PG_DIST_STATUS(pg), 1)); +} + static void hsw_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { enum i915_power_well_id id = power_well->id; + bool wait_fuses = power_well->hsw.has_fuses; + int pg; u32 val; + if (wait_fuses) { + pg = SKL_PW_TO_PG(id); + if (pg == 1) + gen9_wait_for_power_well_fuses(dev_priv, pg - 1); + } + val = I915_READ(HSW_PWR_WELL_DRIVER); I915_WRITE(HSW_PWR_WELL_DRIVER, val | HSW_PWR_WELL_CTL_REQ(id)); hsw_wait_for_power_well_enable(dev_priv, power_well); + if (wait_fuses) + gen9_wait_for_power_well_fuses(dev_priv, pg); + hsw_power_well_post_enable(dev_priv, power_well->hsw.irq_pipe_mask, power_well->hsw.has_vga); } @@ -810,15 +830,15 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, case SKL_DISP_PW_1: if (intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, - SKL_FUSE_PG0_DIST_STATUS, - SKL_FUSE_PG0_DIST_STATUS, + SKL_FUSE_PG_DIST_STATUS(0), + SKL_FUSE_PG_DIST_STATUS(0), 1)) { DRM_ERROR("PG0 not enabled\n"); return; } break; case SKL_DISP_PW_2: - if (!(fuse_status & SKL_FUSE_PG1_DIST_STATUS)) { + if (!(fuse_status & SKL_FUSE_PG_DIST_STATUS(1))) { DRM_ERROR("PG1 in disabled state\n"); return; } @@ -863,15 +883,15 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, if (power_well->id == SKL_DISP_PW_1) { if (intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, - SKL_FUSE_PG1_DIST_STATUS, - SKL_FUSE_PG1_DIST_STATUS, + SKL_FUSE_PG_DIST_STATUS(1), + SKL_FUSE_PG_DIST_STATUS(1), 1)) DRM_ERROR("PG1 distributing status timeout\n"); } else if (power_well->id == SKL_DISP_PW_2) { if (intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, - SKL_FUSE_PG2_DIST_STATUS, - SKL_FUSE_PG2_DIST_STATUS, + SKL_FUSE_PG_DIST_STATUS(2), + SKL_FUSE_PG_DIST_STATUS(2), 1)) DRM_ERROR("PG2 distributing status timeout\n"); } -- 2.7.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx