mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
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 <ssharatkumar@nvidia.com> Reviewed-on: http://git-master/r/921252 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
@@ -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
|
||||
|
||||
66
drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c
Normal file
66
drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c
Normal file
@@ -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 <linux/platform_device.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
25
drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h
Normal file
25
drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h
Normal file
@@ -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_*/
|
||||
@@ -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 <linux/vmalloc.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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 <linux/delay.h> /* for udelay */
|
||||
#include <linux/tegra-fuse.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user