summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/ltc_gm20b.c')
-rw-r--r--drivers/gpu/nvgpu/gm20b/ltc_gm20b.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c
new file mode 100644
index 00000000..134ac491
--- /dev/null
+++ b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c
@@ -0,0 +1,197 @@
1/*
2 * GM20B L2
3 *
4 * Copyright (c) 2014 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/types.h>
17
18#include "hw_ltc_gm20b.h"
19#include "hw_top_gm20b.h"
20#include "hw_proj_gm20b.h"
21#include "hw_pri_ringmaster_gm20b.h"
22
23#include "gk20a/ltc_common.c"
24#include "gk20a/gk20a.h"
25#include "gk20a/gk20a_allocator.h"
26
27static int gm20b_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr)
28{
29 struct device *d = dev_from_gk20a(g);
30 DEFINE_DMA_ATTRS(attrs);
31 dma_addr_t iova;
32
33 /* max memory size (MB) to cover */
34 u32 max_size = gr->max_comptag_mem;
35 /* one tag line covers 128KB */
36 u32 max_comptag_lines = max_size << 3;
37
38 u32 hw_max_comptag_lines =
39 ltc_ltcs_ltss_cbc_ctrl3_clear_upper_bound_init_v();
40
41 u32 cbc_param =
42 gk20a_readl(g, ltc_ltcs_ltss_cbc_param_r());
43 u32 comptags_per_cacheline =
44 ltc_ltcs_ltss_cbc_param_comptags_per_cache_line_v(cbc_param);
45 u32 cacheline_size =
46 512 << ltc_ltcs_ltss_cbc_param_cache_line_size_v(cbc_param);
47 u32 slices_per_ltc =
48 ltc_ltcs_ltss_cbc_param_slices_per_ltc_v(cbc_param);
49
50 u32 compbit_backing_size;
51
52 gk20a_dbg_fn("");
53
54 if (max_comptag_lines == 0) {
55 gr->compbit_store.size = 0;
56 return 0;
57 }
58
59 if (max_comptag_lines > hw_max_comptag_lines)
60 max_comptag_lines = hw_max_comptag_lines;
61
62 /* no hybird fb */
63 compbit_backing_size =
64 DIV_ROUND_UP(max_comptag_lines, comptags_per_cacheline) *
65 cacheline_size * slices_per_ltc * gr->num_fbps;
66
67 /* aligned to 2KB * num_fbps */
68 compbit_backing_size +=
69 gr->num_fbps << ltc_ltcs_ltss_cbc_base_alignment_shift_v();
70
71 /* must be a multiple of 64KB */
72 compbit_backing_size = roundup(compbit_backing_size, 64*1024);
73
74 max_comptag_lines =
75 (compbit_backing_size * comptags_per_cacheline) /
76 cacheline_size * slices_per_ltc * gr->num_fbps;
77
78 if (max_comptag_lines > hw_max_comptag_lines)
79 max_comptag_lines = hw_max_comptag_lines;
80
81 gk20a_dbg_info("compbit backing store size : %d",
82 compbit_backing_size);
83 gk20a_dbg_info("max comptag lines : %d",
84 max_comptag_lines);
85
86 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
87 gr->compbit_store.size = compbit_backing_size;
88 gr->compbit_store.pages = dma_alloc_attrs(d, gr->compbit_store.size,
89 &iova, GFP_KERNEL, &attrs);
90 if (!gr->compbit_store.pages) {
91 gk20a_err(dev_from_gk20a(g), "failed to allocate"
92 "backing store for compbit : size %d",
93 compbit_backing_size);
94 return -ENOMEM;
95 }
96 gr->compbit_store.base_iova = iova;
97
98 gk20a_allocator_init(&gr->comp_tags, "comptag",
99 1, /* start */
100 max_comptag_lines - 1, /* length*/
101 1); /* align */
102
103 return 0;
104}
105
106static int gm20b_ltc_clear_comptags(struct gk20a *g, u32 min, u32 max)
107{
108 struct gr_gk20a *gr = &g->gr;
109 u32 fbp, slice, ctrl1, val;
110 unsigned long end_jiffies = jiffies +
111 msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
112 u32 delay = GR_IDLE_CHECK_DEFAULT;
113 u32 slices_per_ltc = ltc_ltcs_ltss_cbc_param_slices_per_ltc_v(
114 gk20a_readl(g, ltc_ltcs_ltss_cbc_param_r()));
115
116 gk20a_dbg_fn("");
117
118 if (gr->compbit_store.size == 0)
119 return 0;
120
121 gk20a_writel(g, ltc_ltcs_ltss_cbc_ctrl2_r(),
122 ltc_ltcs_ltss_cbc_ctrl2_clear_lower_bound_f(min));
123 gk20a_writel(g, ltc_ltcs_ltss_cbc_ctrl3_r(),
124 ltc_ltcs_ltss_cbc_ctrl3_clear_upper_bound_f(max));
125 gk20a_writel(g, ltc_ltcs_ltss_cbc_ctrl1_r(),
126 gk20a_readl(g, ltc_ltcs_ltss_cbc_ctrl1_r()) |
127 ltc_ltcs_ltss_cbc_ctrl1_clear_active_f());
128
129 for (fbp = 0; fbp < gr->num_fbps; fbp++) {
130 for (slice = 0; slice < slices_per_ltc; slice++) {
131
132 delay = GR_IDLE_CHECK_DEFAULT;
133
134 ctrl1 = ltc_ltc0_lts0_cbc_ctrl1_r() +
135 fbp * proj_ltc_stride_v() +
136 slice * proj_lts_stride_v();
137
138 do {
139 val = gk20a_readl(g, ctrl1);
140 if (ltc_ltcs_ltss_cbc_ctrl1_clear_v(val) !=
141 ltc_ltcs_ltss_cbc_ctrl1_clear_active_v())
142 break;
143
144 usleep_range(delay, delay * 2);
145 delay = min_t(u32, delay << 1,
146 GR_IDLE_CHECK_MAX);
147
148 } while (time_before(jiffies, end_jiffies) |
149 !tegra_platform_is_silicon());
150
151 if (!time_before(jiffies, end_jiffies)) {
152 gk20a_err(dev_from_gk20a(g),
153 "comp tag clear timeout\n");
154 return -EBUSY;
155 }
156 }
157 }
158
159 return 0;
160}
161
162static void gm20b_ltc_init_fs_state(struct gk20a *g)
163{
164 gk20a_dbg_info("initialize gm20b l2");
165
166 g->max_ltc_count = gk20a_readl(g, top_num_ltcs_r());
167 g->ltc_count = gk20a_readl(g, pri_ringmaster_enum_ltc_r());
168 gk20a_dbg_info("%d ltcs out of %d", g->ltc_count, g->max_ltc_count);
169
170 gk20a_writel(g, ltc_ltcs_ltss_cbc_num_active_ltcs_r(),
171 g->ltc_count);
172 gk20a_writel(g, ltc_ltcs_misc_ltc_num_active_ltcs_r(),
173 g->ltc_count);
174
175 gk20a_writel(g, ltc_ltcs_ltss_dstg_cfg0_r(),
176 gk20a_readl(g, ltc_ltc0_lts0_dstg_cfg0_r()) |
177 ltc_ltcs_ltss_dstg_cfg0_vdc_4to2_disable_m());
178}
179
180void gm20b_init_ltc(struct gpu_ops *gops)
181{
182 /* Gk20a reused ops. */
183 gops->ltc.determine_L2_size_bytes = gk20a_determine_L2_size_bytes;
184 gops->ltc.set_max_ways_evict_last = gk20a_ltc_set_max_ways_evict_last;
185 gops->ltc.set_zbc_color_entry = gk20a_ltc_set_zbc_color_entry;
186 gops->ltc.set_zbc_depth_entry = gk20a_ltc_set_zbc_depth_entry;
187 gops->ltc.clear_zbc_color_entry = gk20a_ltc_clear_zbc_color_entry;
188 gops->ltc.clear_zbc_depth_entry = gk20a_ltc_clear_zbc_depth_entry;
189 gops->ltc.init_zbc = gk20a_ltc_init_zbc;
190 gops->ltc.init_cbc = gk20a_ltc_init_cbc;
191
192 /* GM20b specific ops. */
193 gops->ltc.init_fs_state = gm20b_ltc_init_fs_state;
194 gops->ltc.init_comptags = gm20b_ltc_init_comptags;
195 gops->ltc.clear_comptags = gm20b_ltc_clear_comptags;
196 gops->ltc.elpg_flush = gk20a_mm_g_elpg_flush_locked;
197}