diff options
author | Mahantesh Kumbar <mkumbar@nvidia.com> | 2017-06-21 11:06:26 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-06-27 06:57:45 -0400 |
commit | b7b38d1cd6177dec55de993b4d674948d7c587ef (patch) | |
tree | d3275df64a6e6c5785c5f2aebb2d42fdf59194ce /drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | |
parent | 8b3d94ffd3e5b6d7a622c6ad54692d79bf39d1ce (diff) |
gpu: nvgpu: falcon copy from DMEM
- Added interface/HAL method for falcon
to support copy from dmem
- Method to read dmem size
- Method to check error on input parameters
JIRA NVGPU-99
Change-Id: Id27b2b7f4f338196fc3b187555718543445d35bd
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: https://git-master/r/1506525
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/flcn_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 90 |
1 files changed, 90 insertions, 0 deletions
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 | ||
110 | static 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 | |||
127 | static 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 | |||
155 | static 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 | |||
110 | static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) | 198 | static 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", |