drm/i915: split out vlv sideband to a separate file
The VLV/CHV sideband code is pretty distinct from the rest of the sideband code. Split it out to new vlv_sideband.[ch]. Pure code movement with relevant #include changes, and a tiny checkpatch fix on top. Cc: Lucas De Marchi <lucas.demarchi@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Lucas De Marchi <lucas.demarchi@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/755ebbbaf01fc6d306b763b6ef60f45e671ba290.1634119597.git.jani.nikula@intel.com
This commit is contained in:
Родитель
c5f44559e9
Коммит
1eecf31e3c
|
@ -54,6 +54,7 @@ i915-y += i915_drv.o \
|
|||
intel_step.o \
|
||||
intel_uncore.o \
|
||||
intel_wakeref.o \
|
||||
vlv_sideband.o \
|
||||
vlv_suspend.o
|
||||
|
||||
# core library code
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
struct dp_link_dpll {
|
||||
int clock;
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_sdvo.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
static void intel_hdmi_prepare(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
/**
|
||||
* DOC: CDCLK / RAWCLK
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#include "i9xx_plane.h"
|
||||
#include "skl_scaler.h"
|
||||
#include "skl_universal_plane.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "intel_hdmi.h"
|
||||
#include "intel_pm.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_sprite.h"
|
||||
|
||||
static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "display/intel_crt.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "intel_cdclk.h"
|
||||
#include "intel_combo_phy.h"
|
||||
#include "intel_crt.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_power.h"
|
||||
#include "intel_display_types.h"
|
||||
|
@ -22,6 +21,7 @@
|
|||
#include "intel_snps_phy.h"
|
||||
#include "intel_tc.h"
|
||||
#include "intel_vga.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum i915_power_well_id power_well_id);
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include "intel_panel.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_tc.h"
|
||||
#include "intel_vdsc.h"
|
||||
#include "intel_vrr.h"
|
||||
|
|
|
@ -21,14 +21,13 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "display/intel_dp.h"
|
||||
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_ddi_buf_trans.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
/**
|
||||
* DOC: DPIO
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
#include "intel_lvds.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_snps_phy.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
struct intel_limit {
|
||||
struct {
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
#define MIPI_TRANSFER_MODE_SHIFT 0
|
||||
#define MIPI_VIRTUAL_CHANNEL_SHIFT 1
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
#include "intel_dsi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "skl_scaler.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
/* return pixels in terms of txbyteclkhs */
|
||||
static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
static const u16 lfsr_converts[] = {
|
||||
426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "intel_runtime_pm.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_uncore.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
static int fw_domains_show(struct seq_file *m, void *data)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "intel_gt_pm_irq.h"
|
||||
#include "intel_rps.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
#include "../../../platform/x86/intel_ips.h"
|
||||
|
||||
#define BUSY_MAX_EI 20u /* ms */
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "i915_scheduler.h"
|
||||
#include "i915_trace.h"
|
||||
#include "intel_pm.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "i915_drv.h"
|
||||
#include "i915_sysfs.h"
|
||||
#include "intel_pm.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "i915_trace.h"
|
||||
#include "intel_pm.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "vlv_sideband.h"
|
||||
#include "../../../platform/x86/intel_ips.h"
|
||||
|
||||
/* Stores plane specific WM parameters */
|
||||
|
|
|
@ -27,263 +27,6 @@
|
|||
#include "i915_drv.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
/*
|
||||
* IOSF sideband, see VLV2_SidebandMsg_HAS.docx and
|
||||
* VLV_VLV2_PUNIT_HAS_0.8.docx
|
||||
*/
|
||||
|
||||
/* Standard MMIO read, non-posted */
|
||||
#define SB_MRD_NP 0x00
|
||||
/* Standard MMIO write, non-posted */
|
||||
#define SB_MWR_NP 0x01
|
||||
/* Private register read, double-word addressing, non-posted */
|
||||
#define SB_CRRDDA_NP 0x06
|
||||
/* Private register write, double-word addressing, non-posted */
|
||||
#define SB_CRWRDA_NP 0x07
|
||||
|
||||
static void ping(void *info)
|
||||
{
|
||||
}
|
||||
|
||||
static void __vlv_punit_get(struct drm_i915_private *i915)
|
||||
{
|
||||
iosf_mbi_punit_acquire();
|
||||
|
||||
/*
|
||||
* Prevent the cpu from sleeping while we use this sideband, otherwise
|
||||
* the punit may cause a machine hang. The issue appears to be isolated
|
||||
* with changing the power state of the CPU package while changing
|
||||
* the power state via the punit, and we have only observed it
|
||||
* reliably on 4-core Baytail systems suggesting the issue is in the
|
||||
* power delivery mechanism and likely to be be board/function
|
||||
* specific. Hence we presume the workaround needs only be applied
|
||||
* to the Valleyview P-unit and not all sideband communications.
|
||||
*/
|
||||
if (IS_VALLEYVIEW(i915)) {
|
||||
cpu_latency_qos_update_request(&i915->sb_qos, 0);
|
||||
on_each_cpu(ping, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void __vlv_punit_put(struct drm_i915_private *i915)
|
||||
{
|
||||
if (IS_VALLEYVIEW(i915))
|
||||
cpu_latency_qos_update_request(&i915->sb_qos,
|
||||
PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
iosf_mbi_punit_release();
|
||||
}
|
||||
|
||||
void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports)
|
||||
{
|
||||
if (ports & BIT(VLV_IOSF_SB_PUNIT))
|
||||
__vlv_punit_get(i915);
|
||||
|
||||
mutex_lock(&i915->sb_lock);
|
||||
}
|
||||
|
||||
void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports)
|
||||
{
|
||||
mutex_unlock(&i915->sb_lock);
|
||||
|
||||
if (ports & BIT(VLV_IOSF_SB_PUNIT))
|
||||
__vlv_punit_put(i915);
|
||||
}
|
||||
|
||||
static int vlv_sideband_rw(struct drm_i915_private *i915,
|
||||
u32 devfn, u32 port, u32 opcode,
|
||||
u32 addr, u32 *val)
|
||||
{
|
||||
struct intel_uncore *uncore = &i915->uncore;
|
||||
const bool is_read = (opcode == SB_MRD_NP || opcode == SB_CRRDDA_NP);
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&i915->sb_lock);
|
||||
if (port == IOSF_PORT_PUNIT)
|
||||
iosf_mbi_assert_punit_acquired();
|
||||
|
||||
/* Flush the previous comms, just in case it failed last time. */
|
||||
if (intel_wait_for_register(uncore,
|
||||
VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0,
|
||||
5)) {
|
||||
drm_dbg(&i915->drm, "IOSF sideband idle wait (%s) timed out\n",
|
||||
is_read ? "read" : "write");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
|
||||
intel_uncore_write_fw(uncore, VLV_IOSF_ADDR, addr);
|
||||
intel_uncore_write_fw(uncore, VLV_IOSF_DATA, is_read ? 0 : *val);
|
||||
intel_uncore_write_fw(uncore, VLV_IOSF_DOORBELL_REQ,
|
||||
(devfn << IOSF_DEVFN_SHIFT) |
|
||||
(opcode << IOSF_OPCODE_SHIFT) |
|
||||
(port << IOSF_PORT_SHIFT) |
|
||||
(0xf << IOSF_BYTE_ENABLES_SHIFT) |
|
||||
(0 << IOSF_BAR_SHIFT) |
|
||||
IOSF_SB_BUSY);
|
||||
|
||||
if (__intel_wait_for_register_fw(uncore,
|
||||
VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0,
|
||||
10000, 0, NULL) == 0) {
|
||||
if (is_read)
|
||||
*val = intel_uncore_read_fw(uncore, VLV_IOSF_DATA);
|
||||
err = 0;
|
||||
} else {
|
||||
drm_dbg(&i915->drm, "IOSF sideband finish wait (%s) timed out\n",
|
||||
is_read ? "read" : "write");
|
||||
err = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
|
||||
SB_CRRDDA_NP, addr, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val)
|
||||
{
|
||||
return vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
|
||||
SB_CRWRDA_NP, addr, &val);
|
||||
}
|
||||
|
||||
u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_NC,
|
||||
SB_CRRDDA_NP, addr, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_iosf_sb_write(struct drm_i915_private *i915,
|
||||
u8 port, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy)
|
||||
{
|
||||
/*
|
||||
* IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D)
|
||||
* IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C)
|
||||
*/
|
||||
if (IS_CHERRYVIEW(i915))
|
||||
return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO;
|
||||
else
|
||||
return IOSF_PORT_DPIO;
|
||||
}
|
||||
|
||||
u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg)
|
||||
{
|
||||
u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe));
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val);
|
||||
|
||||
/*
|
||||
* FIXME: There might be some registers where all 1's is a valid value,
|
||||
* so ideally we should check the register offset instead...
|
||||
*/
|
||||
drm_WARN(&i915->drm, val == 0xffffffff,
|
||||
"DPIO read pipe %c reg 0x%x == 0x%x\n",
|
||||
pipe_name(pipe), reg, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_dpio_write(struct drm_i915_private *i915,
|
||||
enum pipe pipe, int reg, u32 val)
|
||||
{
|
||||
u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe));
|
||||
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP,
|
||||
reg, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP,
|
||||
reg, &val);
|
||||
}
|
||||
|
||||
/* SBI access */
|
||||
static int intel_sbi_rw(struct drm_i915_private *i915, u16 reg,
|
||||
enum intel_sbi_destination destination,
|
||||
|
|
|
@ -3,125 +3,15 @@
|
|||
#ifndef _INTEL_SIDEBAND_H_
|
||||
#define _INTEL_SIDEBAND_H_
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
enum pipe;
|
||||
|
||||
enum intel_sbi_destination {
|
||||
SBI_ICLK,
|
||||
SBI_MPHY,
|
||||
};
|
||||
|
||||
enum {
|
||||
VLV_IOSF_SB_BUNIT,
|
||||
VLV_IOSF_SB_CCK,
|
||||
VLV_IOSF_SB_CCU,
|
||||
VLV_IOSF_SB_DPIO,
|
||||
VLV_IOSF_SB_FLISDSI,
|
||||
VLV_IOSF_SB_GPIO,
|
||||
VLV_IOSF_SB_NC,
|
||||
VLV_IOSF_SB_PUNIT,
|
||||
};
|
||||
|
||||
void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports);
|
||||
u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg);
|
||||
void vlv_iosf_sb_write(struct drm_i915_private *i915,
|
||||
u8 port, u32 reg, u32 val);
|
||||
void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports);
|
||||
|
||||
static inline void vlv_bunit_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT));
|
||||
}
|
||||
|
||||
u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_bunit_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT));
|
||||
}
|
||||
|
||||
static inline void vlv_cck_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK));
|
||||
}
|
||||
|
||||
u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_cck_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK));
|
||||
}
|
||||
|
||||
static inline void vlv_ccu_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU));
|
||||
}
|
||||
|
||||
u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_ccu_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU));
|
||||
}
|
||||
|
||||
static inline void vlv_dpio_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO));
|
||||
}
|
||||
|
||||
u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg);
|
||||
void vlv_dpio_write(struct drm_i915_private *i915,
|
||||
enum pipe pipe, int reg, u32 val);
|
||||
|
||||
static inline void vlv_dpio_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO));
|
||||
}
|
||||
|
||||
static inline void vlv_flisdsi_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI));
|
||||
}
|
||||
|
||||
u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_flisdsi_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI));
|
||||
}
|
||||
|
||||
static inline void vlv_nc_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC));
|
||||
}
|
||||
|
||||
u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr);
|
||||
|
||||
static inline void vlv_nc_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC));
|
||||
}
|
||||
|
||||
static inline void vlv_punit_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT));
|
||||
}
|
||||
|
||||
u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr);
|
||||
int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val);
|
||||
|
||||
static inline void vlv_punit_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT));
|
||||
}
|
||||
|
||||
u32 intel_sbi_read(struct drm_i915_private *i915, u16 reg,
|
||||
enum intel_sbi_destination destination);
|
||||
void intel_sbi_write(struct drm_i915_private *i915, u16 reg, u32 value,
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2013-2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <asm/iosf_mbi.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
/*
|
||||
* IOSF sideband, see VLV2_SidebandMsg_HAS.docx and
|
||||
* VLV_VLV2_PUNIT_HAS_0.8.docx
|
||||
*/
|
||||
|
||||
/* Standard MMIO read, non-posted */
|
||||
#define SB_MRD_NP 0x00
|
||||
/* Standard MMIO write, non-posted */
|
||||
#define SB_MWR_NP 0x01
|
||||
/* Private register read, double-word addressing, non-posted */
|
||||
#define SB_CRRDDA_NP 0x06
|
||||
/* Private register write, double-word addressing, non-posted */
|
||||
#define SB_CRWRDA_NP 0x07
|
||||
|
||||
static void ping(void *info)
|
||||
{
|
||||
}
|
||||
|
||||
static void __vlv_punit_get(struct drm_i915_private *i915)
|
||||
{
|
||||
iosf_mbi_punit_acquire();
|
||||
|
||||
/*
|
||||
* Prevent the cpu from sleeping while we use this sideband, otherwise
|
||||
* the punit may cause a machine hang. The issue appears to be isolated
|
||||
* with changing the power state of the CPU package while changing
|
||||
* the power state via the punit, and we have only observed it
|
||||
* reliably on 4-core Baytail systems suggesting the issue is in the
|
||||
* power delivery mechanism and likely to be board/function
|
||||
* specific. Hence we presume the workaround needs only be applied
|
||||
* to the Valleyview P-unit and not all sideband communications.
|
||||
*/
|
||||
if (IS_VALLEYVIEW(i915)) {
|
||||
cpu_latency_qos_update_request(&i915->sb_qos, 0);
|
||||
on_each_cpu(ping, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void __vlv_punit_put(struct drm_i915_private *i915)
|
||||
{
|
||||
if (IS_VALLEYVIEW(i915))
|
||||
cpu_latency_qos_update_request(&i915->sb_qos,
|
||||
PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
iosf_mbi_punit_release();
|
||||
}
|
||||
|
||||
void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports)
|
||||
{
|
||||
if (ports & BIT(VLV_IOSF_SB_PUNIT))
|
||||
__vlv_punit_get(i915);
|
||||
|
||||
mutex_lock(&i915->sb_lock);
|
||||
}
|
||||
|
||||
void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports)
|
||||
{
|
||||
mutex_unlock(&i915->sb_lock);
|
||||
|
||||
if (ports & BIT(VLV_IOSF_SB_PUNIT))
|
||||
__vlv_punit_put(i915);
|
||||
}
|
||||
|
||||
static int vlv_sideband_rw(struct drm_i915_private *i915,
|
||||
u32 devfn, u32 port, u32 opcode,
|
||||
u32 addr, u32 *val)
|
||||
{
|
||||
struct intel_uncore *uncore = &i915->uncore;
|
||||
const bool is_read = (opcode == SB_MRD_NP || opcode == SB_CRRDDA_NP);
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&i915->sb_lock);
|
||||
if (port == IOSF_PORT_PUNIT)
|
||||
iosf_mbi_assert_punit_acquired();
|
||||
|
||||
/* Flush the previous comms, just in case it failed last time. */
|
||||
if (intel_wait_for_register(uncore,
|
||||
VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0,
|
||||
5)) {
|
||||
drm_dbg(&i915->drm, "IOSF sideband idle wait (%s) timed out\n",
|
||||
is_read ? "read" : "write");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
|
||||
intel_uncore_write_fw(uncore, VLV_IOSF_ADDR, addr);
|
||||
intel_uncore_write_fw(uncore, VLV_IOSF_DATA, is_read ? 0 : *val);
|
||||
intel_uncore_write_fw(uncore, VLV_IOSF_DOORBELL_REQ,
|
||||
(devfn << IOSF_DEVFN_SHIFT) |
|
||||
(opcode << IOSF_OPCODE_SHIFT) |
|
||||
(port << IOSF_PORT_SHIFT) |
|
||||
(0xf << IOSF_BYTE_ENABLES_SHIFT) |
|
||||
(0 << IOSF_BAR_SHIFT) |
|
||||
IOSF_SB_BUSY);
|
||||
|
||||
if (__intel_wait_for_register_fw(uncore,
|
||||
VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0,
|
||||
10000, 0, NULL) == 0) {
|
||||
if (is_read)
|
||||
*val = intel_uncore_read_fw(uncore, VLV_IOSF_DATA);
|
||||
err = 0;
|
||||
} else {
|
||||
drm_dbg(&i915->drm, "IOSF sideband finish wait (%s) timed out\n",
|
||||
is_read ? "read" : "write");
|
||||
err = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
|
||||
SB_CRRDDA_NP, addr, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val)
|
||||
{
|
||||
return vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
|
||||
SB_CRWRDA_NP, addr, &val);
|
||||
}
|
||||
|
||||
u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_NC,
|
||||
SB_CRRDDA_NP, addr, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_iosf_sb_write(struct drm_i915_private *i915,
|
||||
u8 port, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
|
||||
SB_CRRDDA_NP, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
|
||||
SB_CRWRDA_NP, reg, &val);
|
||||
}
|
||||
|
||||
static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy)
|
||||
{
|
||||
/*
|
||||
* IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D)
|
||||
* IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C)
|
||||
*/
|
||||
if (IS_CHERRYVIEW(i915))
|
||||
return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO;
|
||||
else
|
||||
return IOSF_PORT_DPIO;
|
||||
}
|
||||
|
||||
u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg)
|
||||
{
|
||||
u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe));
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val);
|
||||
|
||||
/*
|
||||
* FIXME: There might be some registers where all 1's is a valid value,
|
||||
* so ideally we should check the register offset instead...
|
||||
*/
|
||||
drm_WARN(&i915->drm, val == 0xffffffff,
|
||||
"DPIO read pipe %c reg 0x%x == 0x%x\n",
|
||||
pipe_name(pipe), reg, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_dpio_write(struct drm_i915_private *i915,
|
||||
enum pipe pipe, int reg, u32 val)
|
||||
{
|
||||
u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe));
|
||||
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val);
|
||||
}
|
||||
|
||||
u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP,
|
||||
reg, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val)
|
||||
{
|
||||
vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP,
|
||||
reg, &val);
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2013-2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef _VLV_SIDEBAND_H_
|
||||
#define _VLV_SIDEBAND_H_
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
enum pipe;
|
||||
struct drm_i915_private;
|
||||
|
||||
enum {
|
||||
VLV_IOSF_SB_BUNIT,
|
||||
VLV_IOSF_SB_CCK,
|
||||
VLV_IOSF_SB_CCU,
|
||||
VLV_IOSF_SB_DPIO,
|
||||
VLV_IOSF_SB_FLISDSI,
|
||||
VLV_IOSF_SB_GPIO,
|
||||
VLV_IOSF_SB_NC,
|
||||
VLV_IOSF_SB_PUNIT,
|
||||
};
|
||||
|
||||
void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports);
|
||||
u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg);
|
||||
void vlv_iosf_sb_write(struct drm_i915_private *i915,
|
||||
u8 port, u32 reg, u32 val);
|
||||
void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports);
|
||||
|
||||
static inline void vlv_bunit_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT));
|
||||
}
|
||||
|
||||
u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_bunit_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT));
|
||||
}
|
||||
|
||||
static inline void vlv_cck_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK));
|
||||
}
|
||||
|
||||
u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_cck_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK));
|
||||
}
|
||||
|
||||
static inline void vlv_ccu_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU));
|
||||
}
|
||||
|
||||
u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_ccu_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU));
|
||||
}
|
||||
|
||||
static inline void vlv_dpio_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO));
|
||||
}
|
||||
|
||||
u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg);
|
||||
void vlv_dpio_write(struct drm_i915_private *i915,
|
||||
enum pipe pipe, int reg, u32 val);
|
||||
|
||||
static inline void vlv_dpio_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO));
|
||||
}
|
||||
|
||||
static inline void vlv_flisdsi_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI));
|
||||
}
|
||||
|
||||
u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg);
|
||||
void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val);
|
||||
|
||||
static inline void vlv_flisdsi_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI));
|
||||
}
|
||||
|
||||
static inline void vlv_nc_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC));
|
||||
}
|
||||
|
||||
u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr);
|
||||
|
||||
static inline void vlv_nc_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC));
|
||||
}
|
||||
|
||||
static inline void vlv_punit_get(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT));
|
||||
}
|
||||
|
||||
u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr);
|
||||
int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val);
|
||||
|
||||
static inline void vlv_punit_put(struct drm_i915_private *i915)
|
||||
{
|
||||
vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT));
|
||||
}
|
||||
|
||||
#endif /* _VLV_SIDEBAND_H_ */
|
Загрузка…
Ссылка в новой задаче