diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-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 0542fd67..8b930bca 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 00000000..800f39c3 --- /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 00000000..c1d101da --- /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 90d0ce8d..9eea7d43 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 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) | |||
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 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 @@ | |||
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 00701a50..6a704813 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 | } |