diff options
| author | Supriya <ssharatkumar@nvidia.com> | 2015-12-10 02:24:38 -0500 |
|---|---|---|
| committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-02-26 15:30:56 -0500 |
| commit | a0b75eba5e9ac8869911af445ca7fe3b29c694df (patch) | |
| tree | 0e49d9ea297c4b0a48d643ab9096db3b3167090c /drivers/gpu | |
| parent | 7267c59d412a183afd541624e04ffc175ee25784 (diff) | |
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>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/Makefile | 3 | ||||
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c | 66 | ||||
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h | 25 | ||||
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/gr_gp10b.c | 10 | ||||
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/nvgpu/gp10b/pmu_gp10b.c | 76 |
7 files changed, 187 insertions, 5 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/Makefile b/drivers/gpu/nvgpu/gp10b/Makefile index 0542fd678..8b930bca4 100644 --- a/drivers/gpu/nvgpu/gp10b/Makefile +++ b/drivers/gpu/nvgpu/gp10b/Makefile | |||
| @@ -25,6 +25,7 @@ obj-$(CONFIG_GK20A) += \ | |||
| 25 | gp10b_gating_reglist.o \ | 25 | gp10b_gating_reglist.o \ |
| 26 | regops_gp10b.o \ | 26 | regops_gp10b.o \ |
| 27 | cde_gp10b.o \ | 27 | cde_gp10b.o \ |
| 28 | therm_gp10b.o | 28 | therm_gp10b.o \ |
| 29 | gp10b_sysfs.o | ||
| 29 | 30 | ||
| 30 | obj-$(CONFIG_TEGRA_GK20A) += platform_gp10b_tegra.o | 31 | 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 000000000..800f39c3e --- /dev/null +++ b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | /* | ||
| 2 | * GP10B specific sysfs files | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/platform_device.h> | ||
| 17 | |||
| 18 | #include "gk20a/gk20a.h" | ||
| 19 | #include "gp10b_sysfs.h" | ||
| 20 | |||
| 21 | #define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) | ||
| 22 | |||
| 23 | static ssize_t ecc_enable_store(struct device *device, | ||
| 24 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 25 | { | ||
| 26 | struct platform_device *ndev = to_platform_device(device); | ||
| 27 | struct gk20a *g = get_gk20a(ndev); | ||
| 28 | u32 ecc_mask; | ||
| 29 | u32 err = 0; | ||
| 30 | |||
| 31 | err = sscanf(buf, "%d", &ecc_mask); | ||
| 32 | if (err == 1) { | ||
| 33 | err = g->ops.pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd | ||
| 34 | (g, ecc_mask); | ||
| 35 | if (err) | ||
| 36 | dev_err(device, "ECC override did not happen\n"); | ||
| 37 | } else | ||
| 38 | return -EINVAL; | ||
| 39 | return count; | ||
| 40 | } | ||
| 41 | |||
| 42 | static ssize_t ecc_enable_read(struct device *device, | ||
| 43 | struct device_attribute *attr, char *buf) | ||
| 44 | { | ||
| 45 | struct platform_device *ndev = to_platform_device(device); | ||
| 46 | struct gk20a *g = get_gk20a(ndev); | ||
| 47 | |||
| 48 | return sprintf(buf, "ecc override =0x%x\n", | ||
| 49 | g->ops.gr.get_lrf_tex_ltc_dram_override(g)); | ||
| 50 | } | ||
| 51 | |||
| 52 | static DEVICE_ATTR(ecc_enable, ROOTRW, ecc_enable_read, ecc_enable_store); | ||
| 53 | |||
| 54 | void gp10b_create_sysfs(struct platform_device *dev) | ||
| 55 | { | ||
| 56 | int error = 0; | ||
| 57 | |||
| 58 | error |= device_create_file(&dev->dev, &dev_attr_ecc_enable); | ||
| 59 | if (error) | ||
| 60 | dev_err(&dev->dev, "Failed to create sysfs attributes!\n"); | ||
| 61 | } | ||
| 62 | |||
| 63 | void gp10b_remove_sysfs(struct device *dev) | ||
| 64 | { | ||
| 65 | device_remove_file(dev, &dev_attr_ecc_enable); | ||
| 66 | } | ||
diff --git a/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h new file mode 100644 index 000000000..c1d101daf --- /dev/null +++ b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * GP10B specific sysfs files | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef _GP10B_SYSFS_H_ | ||
| 17 | #define _GP10B_SYSFS_H_ | ||
| 18 | |||
| 19 | /*ECC Fuse*/ | ||
| 20 | #define FUSE_OPT_ECC_EN 0x358 | ||
| 21 | |||
| 22 | void gp10b_create_sysfs(struct platform_device *dev); | ||
| 23 | void gp10b_remove_sysfs(struct device *dev); | ||
| 24 | |||
| 25 | #endif /*_GP10B_SYSFS_H_*/ | ||
diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c index 90d0ce8d7..9eea7d436 100644 --- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "hw_proj_gp10b.h" | 28 | #include "hw_proj_gp10b.h" |
| 29 | #include "hw_ctxsw_prog_gp10b.h" | 29 | #include "hw_ctxsw_prog_gp10b.h" |
| 30 | #include "hw_mc_gp10b.h" | 30 | #include "hw_mc_gp10b.h" |
| 31 | #include "gp10b_sysfs.h" | ||
| 31 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
| 32 | 33 | ||
| 33 | static bool gr_gp10b_is_valid_class(struct gk20a *g, u32 class_num) | 34 | 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) | |||
| 1702 | return hww_warp_esr; | 1703 | return hww_warp_esr; |
| 1703 | } | 1704 | } |
| 1704 | 1705 | ||
| 1706 | static u32 get_ecc_override_val(struct gk20a *g) | ||
| 1707 | { | ||
| 1708 | if (tegra_fuse_readl(FUSE_OPT_ECC_EN)) | ||
| 1709 | return gk20a_readl(g, gr_fecs_feature_override_ecc_r()); | ||
| 1710 | else | ||
| 1711 | return 0; | ||
| 1712 | } | ||
| 1713 | |||
| 1705 | void gp10b_init_gr(struct gpu_ops *gops) | 1714 | void gp10b_init_gr(struct gpu_ops *gops) |
| 1706 | { | 1715 | { |
| 1707 | gm20b_init_gr(gops); | 1716 | gm20b_init_gr(gops); |
| @@ -1739,4 +1748,5 @@ void gp10b_init_gr(struct gpu_ops *gops) | |||
| 1739 | gr_gp10b_pre_process_sm_exception; | 1748 | gr_gp10b_pre_process_sm_exception; |
| 1740 | gops->gr.handle_fecs_error = gr_gp10b_handle_fecs_error; | 1749 | gops->gr.handle_fecs_error = gr_gp10b_handle_fecs_error; |
| 1741 | gops->gr.create_gr_sysfs = gr_gp10b_create_sysfs; | 1750 | gops->gr.create_gr_sysfs = gr_gp10b_create_sysfs; |
| 1751 | gops->gr.get_lrf_tex_ltc_dram_override = get_ecc_override_val; | ||
| 1742 | } | 1752 | } |
diff --git a/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h b/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h index 0480527c9..62ac13274 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) | |||
| 1478 | { | 1478 | { |
| 1479 | return 0x00409420; | 1479 | return 0x00409420; |
| 1480 | } | 1480 | } |
| 1481 | static inline u32 gr_fecs_feature_override_ecc_r(void) | ||
| 1482 | { | ||
| 1483 | return 0x00409658; | ||
| 1484 | } | ||
| 1481 | static inline u32 gr_gpc0_gpccs_ctxsw_idlestate_r(void) | 1485 | static inline u32 gr_gpc0_gpccs_ctxsw_idlestate_r(void) |
| 1482 | { | 1486 | { |
| 1483 | return 0x00502420; | 1487 | return 0x00502420; |
diff --git a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c index 3221e4233..c4a5179a0 100644 --- a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "ltc_gp10b.h" | 34 | #include "ltc_gp10b.h" |
| 35 | #include "hw_gr_gp10b.h" | 35 | #include "hw_gr_gp10b.h" |
| 36 | #include "hw_ltc_gp10b.h" | 36 | #include "hw_ltc_gp10b.h" |
| 37 | #include "gp10b_sysfs.h" | ||
| 37 | 38 | ||
| 38 | #define GP10B_MAX_SUPPORTED_FREQS 11 | 39 | #define GP10B_MAX_SUPPORTED_FREQS 11 |
| 39 | static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; | 40 | static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; |
| @@ -142,7 +143,8 @@ static int gp10b_tegra_late_probe(struct platform_device *pdev) | |||
| 142 | { | 143 | { |
| 143 | /* Make gk20a power domain a subdomain of host1x */ | 144 | /* Make gk20a power domain a subdomain of host1x */ |
| 144 | nvhost_register_client_domain(dev_to_genpd(&pdev->dev)); | 145 | nvhost_register_client_domain(dev_to_genpd(&pdev->dev)); |
| 145 | 146 | /*Create GP10B specific sysfs*/ | |
| 147 | gp10b_create_sysfs(pdev); | ||
| 146 | return 0; | 148 | return 0; |
| 147 | } | 149 | } |
| 148 | 150 | ||
| @@ -150,9 +152,9 @@ static int gp10b_tegra_remove(struct platform_device *pdev) | |||
| 150 | { | 152 | { |
| 151 | /* remove gk20a power subdomain from host1x */ | 153 | /* remove gk20a power subdomain from host1x */ |
| 152 | nvhost_unregister_client_domain(dev_to_genpd(&pdev->dev)); | 154 | nvhost_unregister_client_domain(dev_to_genpd(&pdev->dev)); |
| 153 | |||
| 154 | gr_gp10b_remove_sysfs(&pdev->dev); | 155 | gr_gp10b_remove_sysfs(&pdev->dev); |
| 155 | 156 | /*Remove GP10B specific sysfs*/ | |
| 157 | gp10b_remove_sysfs(&pdev->dev); | ||
| 156 | return 0; | 158 | return 0; |
| 157 | 159 | ||
| 158 | } | 160 | } |
diff --git a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c index 00701a50f..6a7048130 100644 --- a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * GP10B PMU | 2 | * GP10B PMU |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| 8 | * version 2, as published by the Free Software Foundation. | 8 | * version 2, as published by the Free Software Foundation. |
| @@ -14,6 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/delay.h> /* for udelay */ | 16 | #include <linux/delay.h> /* for udelay */ |
| 17 | #include <linux/tegra-fuse.h> | ||
| 17 | #include "gk20a/gk20a.h" | 18 | #include "gk20a/gk20a.h" |
| 18 | #include "gk20a/pmu_gk20a.h" | 19 | #include "gk20a/pmu_gk20a.h" |
| 19 | #include "gm20b/acr_gm20b.h" | 20 | #include "gm20b/acr_gm20b.h" |
| @@ -21,6 +22,7 @@ | |||
| 21 | 22 | ||
| 22 | #include "pmu_gp10b.h" | 23 | #include "pmu_gp10b.h" |
| 23 | #include "hw_pwr_gp10b.h" | 24 | #include "hw_pwr_gp10b.h" |
| 25 | #include "gp10b_sysfs.h" | ||
| 24 | 26 | ||
| 25 | #define gp10b_dbg_pmu(fmt, arg...) \ | 27 | #define gp10b_dbg_pmu(fmt, arg...) \ |
| 26 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) | 28 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) |
| @@ -324,6 +326,76 @@ static int gp10b_init_pmu_setup_hw1(struct gk20a *g) | |||
| 324 | 326 | ||
| 325 | } | 327 | } |
| 326 | 328 | ||
| 329 | static void pmu_handle_ecc_en_dis_msg(struct gk20a *g, struct pmu_msg *msg, | ||
| 330 | void *param, u32 handle, u32 status) | ||
| 331 | { | ||
| 332 | struct pmu_gk20a *pmu = &g->pmu; | ||
| 333 | struct pmu_msg_lrf_tex_ltc_dram_en_dis *ecc = | ||
| 334 | &msg->msg.lrf_tex_ltc_dram.en_dis; | ||
| 335 | gk20a_dbg_fn(""); | ||
| 336 | |||
| 337 | if (status != 0) { | ||
| 338 | gk20a_err(dev_from_gk20a(g), "ECC en dis cmd aborted"); | ||
| 339 | return; | ||
| 340 | } | ||
| 341 | if (msg->msg.lrf_tex_ltc_dram.msg_type != | ||
| 342 | PMU_LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS) { | ||
| 343 | gk20a_err(dev_from_gk20a(g), | ||
| 344 | "Invalid msg for LRF_TEX_LTC_DRAM_CMD_ID_EN_DIS cmd"); | ||
| 345 | return; | ||
| 346 | } else if (ecc->pmu_status != 0) { | ||
| 347 | gk20a_err(dev_from_gk20a(g), | ||
| 348 | "LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg status = %x", | ||
| 349 | ecc->pmu_status); | ||
| 350 | gk20a_err(dev_from_gk20a(g), | ||
| 351 | "LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg en fail = %x", | ||
| 352 | ecc->en_fail_mask); | ||
| 353 | gk20a_err(dev_from_gk20a(g), | ||
| 354 | "LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg dis fail = %x", | ||
| 355 | ecc->dis_fail_mask); | ||
| 356 | } else | ||
| 357 | pmu->override_done = 1; | ||
| 358 | gk20a_dbg_fn("done"); | ||
| 359 | } | ||
| 360 | |||
| 361 | static int send_ecc_overide_en_dis_cmd(struct gk20a *g, u32 bitmask) | ||
| 362 | { | ||
| 363 | struct pmu_gk20a *pmu = &g->pmu; | ||
| 364 | struct pmu_cmd cmd; | ||
| 365 | u32 seq; | ||
| 366 | int status; | ||
| 367 | gk20a_dbg_fn(""); | ||
| 368 | |||
| 369 | if (!tegra_fuse_readl(FUSE_OPT_ECC_EN)) { | ||
| 370 | gk20a_err(dev_from_gk20a(g), "Board not ECC capable"); | ||
| 371 | return -1; | ||
| 372 | } | ||
| 373 | if (!(g->acr.capabilities & | ||
| 374 | ACR_LRF_TEX_LTC_DRAM_PRIV_MASK_ENABLE_LS_OVERRIDE)) { | ||
| 375 | gk20a_err(dev_from_gk20a(g), "check ACR capabilities"); | ||
| 376 | return -1; | ||
| 377 | } | ||
| 378 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
| 379 | cmd.hdr.unit_id = PMU_UNIT_FECS_MEM_OVERRIDE; | ||
| 380 | cmd.hdr.size = PMU_CMD_HDR_SIZE + | ||
| 381 | sizeof(struct pmu_cmd_lrf_tex_ltc_dram_en_dis); | ||
| 382 | cmd.cmd.lrf_tex_ltc_dram.en_dis.cmd_type = | ||
| 383 | PMU_LRF_TEX_LTC_DRAM_CMD_ID_EN_DIS; | ||
| 384 | cmd.cmd.lrf_tex_ltc_dram.en_dis.en_dis_mask = (u8)(bitmask & 0xff); | ||
| 385 | |||
| 386 | gp10b_dbg_pmu("cmd post PMU_ECC_CMD_ID_EN_DIS_ECC"); | ||
| 387 | pmu->override_done = 0; | ||
| 388 | status = gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ, | ||
| 389 | pmu_handle_ecc_en_dis_msg, NULL, &seq, ~0); | ||
| 390 | if (status) | ||
| 391 | gk20a_err(dev_from_gk20a(g), "ECC override failed"); | ||
| 392 | else | ||
| 393 | pmu_wait_message_cond(pmu, gk20a_get_gr_idle_timeout(g), | ||
| 394 | &pmu->override_done, 1); | ||
| 395 | gk20a_dbg_fn("done"); | ||
| 396 | return status; | ||
| 397 | } | ||
| 398 | |||
| 327 | void gp10b_init_pmu_ops(struct gpu_ops *gops) | 399 | void gp10b_init_pmu_ops(struct gpu_ops *gops) |
| 328 | { | 400 | { |
| 329 | if (gops->privsecurity) { | 401 | if (gops->privsecurity) { |
| @@ -342,4 +414,6 @@ void gp10b_init_pmu_ops(struct gpu_ops *gops) | |||
| 342 | gops->pmu.write_dmatrfbase = gp10b_write_dmatrfbase; | 414 | gops->pmu.write_dmatrfbase = gp10b_write_dmatrfbase; |
| 343 | gops->pmu.pmu_elpg_statistics = gp10b_pmu_elpg_statistics; | 415 | gops->pmu.pmu_elpg_statistics = gp10b_pmu_elpg_statistics; |
| 344 | gops->pmu.pmu_pg_grinit_param = gp10b_pg_gr_init; | 416 | gops->pmu.pmu_pg_grinit_param = gp10b_pg_gr_init; |
| 417 | gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd = | ||
| 418 | send_ecc_overide_en_dis_cmd; | ||
| 345 | } | 419 | } |
