summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/common/falcon/falcon.c8
-rw-r--r--drivers/gpu/nvgpu/gk20a/flcn_gk20a.c90
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/falcon.h4
3 files changed, 100 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/common/falcon/falcon.c b/drivers/gpu/nvgpu/common/falcon/falcon.c
index 9e832985..4e3ea1a8 100644
--- a/drivers/gpu/nvgpu/common/falcon/falcon.c
+++ b/drivers/gpu/nvgpu/common/falcon/falcon.c
@@ -116,6 +116,14 @@ bool nvgpu_flcn_get_idle_status(struct nvgpu_falcon *flcn)
116 return status; 116 return status;
117} 117}
118 118
119int nvgpu_flcn_copy_from_dmem(struct nvgpu_falcon *flcn,
120 u32 src, u8 *dst, u32 size, u8 port)
121{
122 struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops;
123
124 return flcn_ops->copy_from_dmem(flcn, src, dst, size, port);
125}
126
119void nvgpu_flcn_sw_init(struct gk20a *g, u32 flcn_id) 127void nvgpu_flcn_sw_init(struct gk20a *g, u32 flcn_id)
120{ 128{
121 struct nvgpu_falcon *flcn = NULL; 129 struct nvgpu_falcon *flcn = NULL;
diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c
index 0b140802..cfd2b30a 100644
--- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c
@@ -107,6 +107,94 @@ static bool gk20a_is_falcon_scrubbing_done(struct nvgpu_falcon *flcn)
107 return status; 107 return status;
108} 108}
109 109
110static u32 gk20a_falcon_get_mem_size(struct nvgpu_falcon *flcn, u32 mem_type)
111{
112 struct gk20a *g = flcn->g;
113 u32 mem_size = 0;
114 u32 hw_cfg_reg = gk20a_readl(g,
115 flcn->flcn_base + falcon_falcon_hwcfg_r());
116
117 if (mem_type == MEM_DMEM)
118 mem_size = falcon_falcon_hwcfg_dmem_size_v(hw_cfg_reg)
119 << GK20A_PMU_DMEM_BLKSIZE2;
120 else
121 mem_size = falcon_falcon_hwcfg_imem_size_v(hw_cfg_reg)
122 << GK20A_PMU_DMEM_BLKSIZE2;
123
124 return mem_size;
125}
126
127static int flcn_mem_overflow_check(struct nvgpu_falcon *flcn,
128 u32 offset, u32 size, u32 mem_type)
129{
130 struct gk20a *g = flcn->g;
131 u32 mem_size = 0;
132
133 if (size == 0) {
134 nvgpu_err(g, "size is zero");
135 return -EINVAL;
136 }
137
138 if (offset & 0x3) {
139 nvgpu_err(g, "offset (0x%08x) not 4-byte aligned", offset);
140 return -EINVAL;
141 }
142
143 mem_size = gk20a_falcon_get_mem_size(flcn, mem_type);
144 if (!(offset <= mem_size && (offset + size) <= mem_size)) {
145 nvgpu_err(g, "flcn-id 0x%x, copy overflow ",
146 flcn->flcn_id);
147 nvgpu_err(g, "total size 0x%x, offset 0x%x, copy size 0x%x",
148 mem_size, offset, size);
149 return -EINVAL;
150 }
151
152 return 0;
153}
154
155static int gk20a_flcn_copy_from_dmem(struct nvgpu_falcon *flcn,
156 u32 src, u8 *dst, u32 size, u8 port)
157{
158 struct gk20a *g = flcn->g;
159 u32 base_addr = flcn->flcn_base;
160 u32 i, words, bytes;
161 u32 data, addr_mask;
162 u32 *dst_u32 = (u32 *)dst;
163
164 nvgpu_log_fn(g, " src dmem offset - %x, size - %x", src, size);
165
166 if (flcn_mem_overflow_check(flcn, src, size, MEM_DMEM)) {
167 nvgpu_err(g, "incorrect parameters");
168 return -EINVAL;
169 }
170
171 nvgpu_mutex_acquire(&flcn->copy_lock);
172
173 words = size >> 2;
174 bytes = size & 0x3;
175
176 addr_mask = falcon_falcon_dmemc_offs_m() |
177 falcon_falcon_dmemc_blk_m();
178
179 src &= addr_mask;
180
181 gk20a_writel(g, base_addr + falcon_falcon_dmemc_r(port),
182 src | falcon_falcon_dmemc_aincr_f(1));
183
184 for (i = 0; i < words; i++)
185 dst_u32[i] = gk20a_readl(g,
186 base_addr + falcon_falcon_dmemd_r(port));
187
188 if (bytes > 0) {
189 data = gk20a_readl(g, base_addr + falcon_falcon_dmemd_r(port));
190 for (i = 0; i < bytes; i++)
191 dst[(words << 2) + i] = ((u8 *)&data)[i];
192 }
193
194 nvgpu_mutex_release(&flcn->copy_lock);
195 return 0;
196}
197
110static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) 198static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn)
111{ 199{
112 struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops = 200 struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops =
@@ -135,6 +223,7 @@ static void gk20a_falcon_ops(struct nvgpu_falcon *flcn)
135 flcn_ops->is_falcon_cpu_halted = gk20a_is_falcon_cpu_halted; 223 flcn_ops->is_falcon_cpu_halted = gk20a_is_falcon_cpu_halted;
136 flcn_ops->is_falcon_idle = gk20a_is_falcon_idle; 224 flcn_ops->is_falcon_idle = gk20a_is_falcon_idle;
137 flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; 225 flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done;
226 flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem;
138 227
139 gk20a_falcon_engine_dependency_ops(flcn); 228 gk20a_falcon_engine_dependency_ops(flcn);
140} 229}
@@ -166,6 +255,7 @@ static void gk20a_falcon_hal_sw_init(struct nvgpu_falcon *flcn)
166 } 255 }
167 256
168 if (flcn->is_falcon_supported) { 257 if (flcn->is_falcon_supported) {
258 nvgpu_mutex_init(&flcn->copy_lock);
169 gk20a_falcon_ops(flcn); 259 gk20a_falcon_ops(flcn);
170 } else 260 } else
171 nvgpu_info(g, "flcn-Id 0x%x not supported on current chip", 261 nvgpu_info(g, "flcn-Id 0x%x not supported on current chip",
diff --git a/drivers/gpu/nvgpu/include/nvgpu/falcon.h b/drivers/gpu/nvgpu/include/nvgpu/falcon.h
index 860efa1b..296510bd 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/falcon.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/falcon.h
@@ -172,8 +172,8 @@ void nvgpu_flcn_set_irq(struct nvgpu_falcon *flcn, bool enable,
172bool nvgpu_flcn_get_mem_scrubbing_status(struct nvgpu_falcon *flcn); 172bool nvgpu_flcn_get_mem_scrubbing_status(struct nvgpu_falcon *flcn);
173bool nvgpu_flcn_get_cpu_halted_status(struct nvgpu_falcon *flcn); 173bool nvgpu_flcn_get_cpu_halted_status(struct nvgpu_falcon *flcn);
174bool nvgpu_flcn_get_idle_status(struct nvgpu_falcon *flcn); 174bool nvgpu_flcn_get_idle_status(struct nvgpu_falcon *flcn);
175int nvgpu_flcn_copy_from_mem(struct nvgpu_falcon *flcn, 175int nvgpu_flcn_copy_from_dmem(struct nvgpu_falcon *flcn,
176 enum flcn_mem_type mem_type, u32 src, u8 *dst, u32 size, u8 port); 176 u32 src, u8 *dst, u32 size, u8 port);
177int nvgpu_flcn_copy_to_mem(struct nvgpu_falcon *flcn, 177int nvgpu_flcn_copy_to_mem(struct nvgpu_falcon *flcn,
178 enum flcn_mem_type mem_type, u32 dst, u8 *src, u32 size, u8 port); 178 enum flcn_mem_type mem_type, u32 dst, u8 *src, u32 size, u8 port);
179int nvgpu_flcn_dma_copy(struct nvgpu_falcon *flcn, 179int nvgpu_flcn_dma_copy(struct nvgpu_falcon *flcn,