From cd452a6ed4cad388909b0372f04a0482609acb90 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Thu, 8 Sep 2016 12:13:39 -0700 Subject: gpu: nvgpu: implement PCIe Gen2 frequency swap Implement the ability to swap between different PCIe bus speeds. This code is called during init in case the GPU is not running at the max supported PCIe bus speed. JIRA DNVGPU-89 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1218178 (cherry picked from commit 8dcd3e10f46f524c9bac9fd5dae0f0a899123c23) Change-Id: I21f96110578a68d5c5e30ae21776cff69aefba5d Reviewed-on: http://git-master/r/1227922 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/gk20a.c | 15 +++++++++++++++ drivers/gpu/nvgpu/gk20a/gk20a.h | 15 ++++++++++++++- drivers/gpu/nvgpu/gm206/bios_gm206.c | 1 - drivers/gpu/nvgpu/gm206/bios_gm206.h | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index ff87edc2..c61b47c5 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1040,6 +1040,21 @@ int gk20a_pm_finalize_poweron(struct device *dev) if (g->irq_stall != g->irq_nonstall) enable_irq(g->irq_nonstall); + if (g->ops.xve.available_speeds) { + u32 speed; + + g->ops.xve.sw_init(dev); + g->ops.xve.available_speeds(g, &speed); + + /* Set to max speed */ + speed = 1 << (fls(speed) - 1); + err = g->ops.xve.set_speed(g, speed); + if (err) { + gk20a_err(dev, "Failed to set PCIe bus speed!\n"); + goto done; + } + } + done: return err; } diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index d51fdea1..75b96f42 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -703,6 +703,14 @@ struct gpu_ops { struct gk20a_cs_snapshot_client *client); } css; #endif + struct { + int (*sw_init)(struct device *dev); + int (*get_speed)(struct gk20a *g, u32 *xve_link_speed); + int (*set_speed)(struct gk20a *g, u32 xve_link_speed); + void (*available_speeds)(struct gk20a *g, u32 *speed_mask); + u32 (*xve_readl)(struct gk20a *g, u32 reg); + void (*xve_writel)(struct gk20a *g, u32 reg, u32 val); + } xve; }; struct nvgpu_bios_ucode { @@ -818,7 +826,7 @@ struct gk20a { struct dentry *debugfs_timeslice_medium_priority_us; struct dentry *debugfs_timeslice_high_priority_us; struct dentry *debugfs_runlist_interleave; - + struct dentry *debugfs_xve; #endif struct gk20a_ctxsw_ucode_info ctxsw_ucode_info; @@ -937,6 +945,10 @@ struct gk20a { u16 pci_subsystem_vendor_id, pci_subsystem_device_id; u16 pci_class; u8 pci_revision; + + /* PCIe power states. */ + bool xve_l0s; + bool xve_l1; }; static inline unsigned long gk20a_get_gr_idle_timeout(struct gk20a *g) @@ -1011,6 +1023,7 @@ enum gk20a_dbg_categories { gpu_dbg_sema = BIT(15), /* semaphore debugging */ gpu_dbg_sema_v = BIT(16), /* verbose semaphore debugging */ gpu_dbg_pmu_pstate = BIT(17), /* p state controlled by pmu */ + gpu_dbg_xv = BIT(18), /* XVE debugging */ gpu_dbg_mem = BIT(31), /* memory accesses, very verbose */ }; diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.c b/drivers/gpu/nvgpu/gm206/bios_gm206.c index 7b6a50d0..8693912e 100644 --- a/drivers/gpu/nvgpu/gm206/bios_gm206.c +++ b/drivers/gpu/nvgpu/gm206/bios_gm206.c @@ -29,7 +29,6 @@ #define BIT_HEADER_ID 0xb8ff #define BIT_HEADER_SIGNATURE 0x00544942 #define BIOS_SIZE 0x40000 -#define NV_PCFG 0x88000 #define PCI_EXP_ROM_SIG 0xaa55 #define PCI_EXP_ROM_SIG_NV 0x4e56 #define ROM_FILE_PAYLOAD_OFFSET 0xa00 diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.h b/drivers/gpu/nvgpu/gm206/bios_gm206.h index 5aa20364..1ee4e14c 100644 --- a/drivers/gpu/nvgpu/gm206/bios_gm206.h +++ b/drivers/gpu/nvgpu/gm206/bios_gm206.h @@ -17,6 +17,8 @@ #define PERF_PTRS_WIDTH 0x4 #define PERF_PTRS_WIDTH_16 0x2 +#define NV_PCFG 0x88000 + enum { CLOCKS_TABLE = 2, CLOCK_PROGRAMMING_TABLE, -- cgit v1.2.2