From 640d0e2c3b58294cd11f420a5fc8377d490c43d3 Mon Sep 17 00:00:00 2001 From: Supriya Date: Thu, 10 Dec 2015 12:54:38 +0530 Subject: gpu: nvgpu: ECC override -sysfs functions to call into LS PMU and modify ECC overide register Bug 1699676 Change-Id: Iaf6cc3a86160b806e52ab168577caad42b2c5d22 Signed-off-by: Supriya Reviewed-on: http://git-master/r/921252 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Vijayakumar Subbu GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gp10b/Makefile | 3 +- drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c | 66 ++++++++++++++++++++++ drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h | 25 +++++++++ drivers/gpu/nvgpu/gp10b/gr_gp10b.c | 10 ++++ drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h | 4 ++ drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c | 8 ++- drivers/gpu/nvgpu/gp10b/pmu_gp10b.c | 76 +++++++++++++++++++++++++- 7 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c create mode 100644 drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/gp10b/Makefile b/drivers/gpu/nvgpu/gp10b/Makefile index 0542fd67..8b930bca 100644 --- a/drivers/gpu/nvgpu/gp10b/Makefile +++ b/drivers/gpu/nvgpu/gp10b/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_GK20A) += \ gp10b_gating_reglist.o \ regops_gp10b.o \ cde_gp10b.o \ - therm_gp10b.o + therm_gp10b.o \ + gp10b_sysfs.o obj-$(CONFIG_TEGRA_GK20A) += platform_gp10b_tegra.o diff --git a/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c new file mode 100644 index 00000000..800f39c3 --- /dev/null +++ b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c @@ -0,0 +1,66 @@ +/* + * GP10B specific sysfs files + * + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include + +#include "gk20a/gk20a.h" +#include "gp10b_sysfs.h" + +#define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) + +static ssize_t ecc_enable_store(struct device *device, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *ndev = to_platform_device(device); + struct gk20a *g = get_gk20a(ndev); + u32 ecc_mask; + u32 err = 0; + + err = sscanf(buf, "%d", &ecc_mask); + if (err == 1) { + err = g->ops.pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd + (g, ecc_mask); + if (err) + dev_err(device, "ECC override did not happen\n"); + } else + return -EINVAL; + return count; +} + +static ssize_t ecc_enable_read(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct platform_device *ndev = to_platform_device(device); + struct gk20a *g = get_gk20a(ndev); + + return sprintf(buf, "ecc override =0x%x\n", + g->ops.gr.get_lrf_tex_ltc_dram_override(g)); +} + +static DEVICE_ATTR(ecc_enable, ROOTRW, ecc_enable_read, ecc_enable_store); + +void gp10b_create_sysfs(struct platform_device *dev) +{ + int error = 0; + + error |= device_create_file(&dev->dev, &dev_attr_ecc_enable); + if (error) + dev_err(&dev->dev, "Failed to create sysfs attributes!\n"); +} + +void gp10b_remove_sysfs(struct device *dev) +{ + device_remove_file(dev, &dev_attr_ecc_enable); +} diff --git a/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h new file mode 100644 index 00000000..c1d101da --- /dev/null +++ b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h @@ -0,0 +1,25 @@ +/* + * GP10B specific sysfs files + * + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _GP10B_SYSFS_H_ +#define _GP10B_SYSFS_H_ + +/*ECC Fuse*/ +#define FUSE_OPT_ECC_EN 0x358 + +void gp10b_create_sysfs(struct platform_device *dev); +void gp10b_remove_sysfs(struct device *dev); + +#endif /*_GP10B_SYSFS_H_*/ diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c index 90d0ce8d..9eea7d43 100644 --- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c @@ -28,6 +28,7 @@ #include "hw_proj_gp10b.h" #include "hw_ctxsw_prog_gp10b.h" #include "hw_mc_gp10b.h" +#include "gp10b_sysfs.h" #include static bool gr_gp10b_is_valid_class(struct gk20a *g, u32 class_num) @@ -1702,6 +1703,14 @@ static u32 gp10b_mask_hww_warp_esr(u32 hww_warp_esr) return hww_warp_esr; } +static u32 get_ecc_override_val(struct gk20a *g) +{ + if (tegra_fuse_readl(FUSE_OPT_ECC_EN)) + return gk20a_readl(g, gr_fecs_feature_override_ecc_r()); + else + return 0; +} + void gp10b_init_gr(struct gpu_ops *gops) { gm20b_init_gr(gops); @@ -1739,4 +1748,5 @@ void gp10b_init_gr(struct gpu_ops *gops) gr_gp10b_pre_process_sm_exception; gops->gr.handle_fecs_error = gr_gp10b_handle_fecs_error; gops->gr.create_gr_sysfs = gr_gp10b_create_sysfs; + gops->gr.get_lrf_tex_ltc_dram_override = get_ecc_override_val; } diff --git a/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h b/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h index 0480527c..62ac1327 100644 --- a/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h +++ b/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h @@ -1478,6 +1478,10 @@ static inline u32 gr_fecs_ctxsw_idlestate_r(void) { return 0x00409420; } +static inline u32 gr_fecs_feature_override_ecc_r(void) +{ + return 0x00409658; +} static inline u32 gr_gpc0_gpccs_ctxsw_idlestate_r(void) { return 0x00502420; diff --git a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c index 3221e423..c4a5179a 100644 --- a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c @@ -34,6 +34,7 @@ #include "ltc_gp10b.h" #include "hw_gr_gp10b.h" #include "hw_ltc_gp10b.h" +#include "gp10b_sysfs.h" #define GP10B_MAX_SUPPORTED_FREQS 11 static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; @@ -142,7 +143,8 @@ static int gp10b_tegra_late_probe(struct platform_device *pdev) { /* Make gk20a power domain a subdomain of host1x */ nvhost_register_client_domain(dev_to_genpd(&pdev->dev)); - + /*Create GP10B specific sysfs*/ + gp10b_create_sysfs(pdev); return 0; } @@ -150,9 +152,9 @@ static int gp10b_tegra_remove(struct platform_device *pdev) { /* remove gk20a power subdomain from host1x */ nvhost_unregister_client_domain(dev_to_genpd(&pdev->dev)); - gr_gp10b_remove_sysfs(&pdev->dev); - + /*Remove GP10B specific sysfs*/ + gp10b_remove_sysfs(&pdev->dev); return 0; } diff --git a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c index 00701a50..6a704813 100644 --- a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c @@ -2,7 +2,7 @@ * GP10B PMU * * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. -* + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -14,6 +14,7 @@ */ #include /* for udelay */ +#include #include "gk20a/gk20a.h" #include "gk20a/pmu_gk20a.h" #include "gm20b/acr_gm20b.h" @@ -21,6 +22,7 @@ #include "pmu_gp10b.h" #include "hw_pwr_gp10b.h" +#include "gp10b_sysfs.h" #define gp10b_dbg_pmu(fmt, arg...) \ gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) @@ -324,6 +326,76 @@ static int gp10b_init_pmu_setup_hw1(struct gk20a *g) } +static void pmu_handle_ecc_en_dis_msg(struct gk20a *g, struct pmu_msg *msg, + void *param, u32 handle, u32 status) +{ + struct pmu_gk20a *pmu = &g->pmu; + struct pmu_msg_lrf_tex_ltc_dram_en_dis *ecc = + &msg->msg.lrf_tex_ltc_dram.en_dis; + gk20a_dbg_fn(""); + + if (status != 0) { + gk20a_err(dev_from_gk20a(g), "ECC en dis cmd aborted"); + return; + } + if (msg->msg.lrf_tex_ltc_dram.msg_type != + PMU_LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS) { + gk20a_err(dev_from_gk20a(g), + "Invalid msg for LRF_TEX_LTC_DRAM_CMD_ID_EN_DIS cmd"); + return; + } else if (ecc->pmu_status != 0) { + gk20a_err(dev_from_gk20a(g), + "LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg status = %x", + ecc->pmu_status); + gk20a_err(dev_from_gk20a(g), + "LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg en fail = %x", + ecc->en_fail_mask); + gk20a_err(dev_from_gk20a(g), + "LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg dis fail = %x", + ecc->dis_fail_mask); + } else + pmu->override_done = 1; + gk20a_dbg_fn("done"); +} + +static int send_ecc_overide_en_dis_cmd(struct gk20a *g, u32 bitmask) +{ + struct pmu_gk20a *pmu = &g->pmu; + struct pmu_cmd cmd; + u32 seq; + int status; + gk20a_dbg_fn(""); + + if (!tegra_fuse_readl(FUSE_OPT_ECC_EN)) { + gk20a_err(dev_from_gk20a(g), "Board not ECC capable"); + return -1; + } + if (!(g->acr.capabilities & + ACR_LRF_TEX_LTC_DRAM_PRIV_MASK_ENABLE_LS_OVERRIDE)) { + gk20a_err(dev_from_gk20a(g), "check ACR capabilities"); + return -1; + } + memset(&cmd, 0, sizeof(struct pmu_cmd)); + cmd.hdr.unit_id = PMU_UNIT_FECS_MEM_OVERRIDE; + cmd.hdr.size = PMU_CMD_HDR_SIZE + + sizeof(struct pmu_cmd_lrf_tex_ltc_dram_en_dis); + cmd.cmd.lrf_tex_ltc_dram.en_dis.cmd_type = + PMU_LRF_TEX_LTC_DRAM_CMD_ID_EN_DIS; + cmd.cmd.lrf_tex_ltc_dram.en_dis.en_dis_mask = (u8)(bitmask & 0xff); + + gp10b_dbg_pmu("cmd post PMU_ECC_CMD_ID_EN_DIS_ECC"); + pmu->override_done = 0; + status = gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ, + pmu_handle_ecc_en_dis_msg, NULL, &seq, ~0); + if (status) + gk20a_err(dev_from_gk20a(g), "ECC override failed"); + else + pmu_wait_message_cond(pmu, gk20a_get_gr_idle_timeout(g), + &pmu->override_done, 1); + gk20a_dbg_fn("done"); + return status; +} + void gp10b_init_pmu_ops(struct gpu_ops *gops) { if (gops->privsecurity) { @@ -342,4 +414,6 @@ void gp10b_init_pmu_ops(struct gpu_ops *gops) gops->pmu.write_dmatrfbase = gp10b_write_dmatrfbase; gops->pmu.pmu_elpg_statistics = gp10b_pmu_elpg_statistics; gops->pmu.pmu_pg_grinit_param = gp10b_pg_gr_init; + gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd = + send_ecc_overide_en_dis_cmd; } -- cgit v1.2.2