diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 108 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 5 |
4 files changed, 25 insertions, 94 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c index 9d378248..2a246fdc 100644 --- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * more details. | 11 | * more details. |
12 | */ | 12 | */ |
13 | #include <nvgpu/falcon.h> | 13 | #include <nvgpu/falcon.h> |
14 | #include <nvgpu/pmu.h> | ||
14 | 15 | ||
15 | #include "gk20a/gk20a.h" | 16 | #include "gk20a/gk20a.h" |
16 | 17 | ||
@@ -256,7 +257,7 @@ static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) | |||
256 | 257 | ||
257 | switch (flcn->flcn_id) { | 258 | switch (flcn->flcn_id) { |
258 | case FALCON_ID_PMU: | 259 | case FALCON_ID_PMU: |
259 | flcn_eng_dep_ops->reset_eng = gk20a_pmu_reset; | 260 | flcn_eng_dep_ops->reset_eng = nvgpu_pmu_reset; |
260 | break; | 261 | break; |
261 | default: | 262 | default: |
262 | /* NULL assignment make sure | 263 | /* NULL assignment make sure |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 191d1c39..ff37d9f3 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -755,7 +755,8 @@ struct gpu_ops { | |||
755 | int (*pmu_lpwr_disable_pg)(struct gk20a *g, bool pstate_lock); | 755 | int (*pmu_lpwr_disable_pg)(struct gk20a *g, bool pstate_lock); |
756 | u32 (*pmu_pg_param_post_init)(struct gk20a *g); | 756 | u32 (*pmu_pg_param_post_init)(struct gk20a *g); |
757 | void (*dump_secure_fuses)(struct gk20a *g); | 757 | void (*dump_secure_fuses)(struct gk20a *g); |
758 | int (*reset)(struct gk20a *g); | 758 | int (*reset_engine)(struct gk20a *g, bool do_reset); |
759 | bool (*is_engine_in_reset)(struct gk20a *g); | ||
759 | int (*falcon_wait_for_halt)(struct gk20a *g, | 760 | int (*falcon_wait_for_halt)(struct gk20a *g, |
760 | unsigned int timeout); | 761 | unsigned int timeout); |
761 | int (*falcon_clear_halt_interrupt_status)(struct gk20a *g, | 762 | int (*falcon_clear_halt_interrupt_status)(struct gk20a *g, |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 4a676b82..3fc73e42 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -38,8 +38,6 @@ | |||
38 | #define gk20a_dbg_pmu(fmt, arg...) \ | 38 | #define gk20a_dbg_pmu(fmt, arg...) \ |
39 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) | 39 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) |
40 | 40 | ||
41 | #define PMU_MEM_SCRUBBING_TIMEOUT_MAX 1000 | ||
42 | #define PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT 10 | ||
43 | 41 | ||
44 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos) | 42 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos) |
45 | { | 43 | { |
@@ -159,80 +157,7 @@ void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable) | |||
159 | gk20a_dbg_fn("done"); | 157 | gk20a_dbg_fn("done"); |
160 | } | 158 | } |
161 | 159 | ||
162 | int pmu_enable_hw(struct nvgpu_pmu *pmu, bool enable) | ||
163 | { | ||
164 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
165 | struct nvgpu_timeout timeout; | ||
166 | int err = 0; | ||
167 | |||
168 | gk20a_dbg_fn(""); | ||
169 | |||
170 | if (enable) { | ||
171 | g->ops.mc.enable(g, mc_enable_pwr_enabled_f()); | ||
172 | |||
173 | if (g->ops.clock_gating.slcg_pmu_load_gating_prod) | ||
174 | g->ops.clock_gating.slcg_pmu_load_gating_prod(g, | ||
175 | g->slcg_enabled); | ||
176 | if (g->ops.clock_gating.blcg_pmu_load_gating_prod) | ||
177 | g->ops.clock_gating.blcg_pmu_load_gating_prod(g, | ||
178 | g->blcg_enabled); | ||
179 | |||
180 | nvgpu_timeout_init(g, &timeout, | ||
181 | PMU_MEM_SCRUBBING_TIMEOUT_MAX / | ||
182 | PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT, | ||
183 | NVGPU_TIMER_RETRY_TIMER); | ||
184 | do { | ||
185 | if (nvgpu_flcn_get_mem_scrubbing_status(pmu->flcn)) { | ||
186 | gk20a_dbg_fn("done"); | ||
187 | goto exit; | ||
188 | } | ||
189 | nvgpu_udelay(PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT); | ||
190 | } while (!nvgpu_timeout_expired(&timeout)); | ||
191 | |||
192 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); | ||
193 | nvgpu_err(g, "Falcon mem scrubbing timeout"); | ||
194 | |||
195 | err = -ETIMEDOUT; | ||
196 | } else | ||
197 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); | ||
198 | |||
199 | exit: | ||
200 | return err; | ||
201 | } | ||
202 | 160 | ||
203 | static int pmu_enable(struct nvgpu_pmu *pmu, bool enable) | ||
204 | { | ||
205 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
206 | u32 pmc_enable; | ||
207 | int err; | ||
208 | |||
209 | gk20a_dbg_fn(""); | ||
210 | |||
211 | if (!enable) { | ||
212 | pmc_enable = gk20a_readl(g, mc_enable_r()); | ||
213 | if (mc_enable_pwr_v(pmc_enable) != | ||
214 | mc_enable_pwr_disabled_v()) { | ||
215 | |||
216 | pmu_enable_irq(pmu, false); | ||
217 | pmu_enable_hw(pmu, false); | ||
218 | } | ||
219 | } else { | ||
220 | err = pmu_enable_hw(pmu, true); | ||
221 | if (err) | ||
222 | return err; | ||
223 | |||
224 | /* TBD: post reset */ | ||
225 | |||
226 | err = nvgpu_flcn_wait_idle(pmu->flcn); | ||
227 | if (err) | ||
228 | return err; | ||
229 | |||
230 | pmu_enable_irq(pmu, true); | ||
231 | } | ||
232 | |||
233 | gk20a_dbg_fn("done"); | ||
234 | return 0; | ||
235 | } | ||
236 | 161 | ||
237 | int pmu_bootstrap(struct nvgpu_pmu *pmu) | 162 | int pmu_bootstrap(struct nvgpu_pmu *pmu) |
238 | { | 163 | { |
@@ -576,25 +501,27 @@ static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) | |||
576 | gk20a_writel(g, pwr_falcon_dmatrfbase_r(), addr); | 501 | gk20a_writel(g, pwr_falcon_dmatrfbase_r(), addr); |
577 | } | 502 | } |
578 | 503 | ||
579 | int gk20a_pmu_reset(struct gk20a *g) | 504 | bool gk20a_pmu_is_engine_in_reset(struct gk20a *g) |
580 | { | 505 | { |
581 | struct nvgpu_pmu *pmu = &g->pmu; | 506 | u32 pmc_enable; |
582 | int err; | 507 | bool status = false; |
583 | 508 | ||
584 | err = nvgpu_flcn_wait_idle(pmu->flcn); | 509 | pmc_enable = gk20a_readl(g, mc_enable_r()); |
585 | if (err) | 510 | if (mc_enable_pwr_v(pmc_enable) == |
586 | goto exit; | 511 | mc_enable_pwr_disabled_v()) |
512 | status = true; | ||
587 | 513 | ||
588 | err = pmu_enable(pmu, false); | 514 | return status; |
589 | if (err) | 515 | } |
590 | goto exit; | ||
591 | 516 | ||
592 | err = pmu_enable(pmu, true); | 517 | int gk20a_pmu_engine_reset(struct gk20a *g, bool do_reset) |
593 | if (err) | 518 | { |
594 | goto exit; | 519 | if (do_reset) |
520 | g->ops.mc.enable(g, mc_enable_pwr_enabled_f()); | ||
521 | else | ||
522 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); | ||
595 | 523 | ||
596 | exit: | 524 | return 0; |
597 | return err; | ||
598 | } | 525 | } |
599 | 526 | ||
600 | static bool gk20a_is_pmu_supported(struct gk20a *g) | 527 | static bool gk20a_is_pmu_supported(struct gk20a *g) |
@@ -650,7 +577,8 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops) | |||
650 | gops->pmu.alloc_blob_space = NULL; | 577 | gops->pmu.alloc_blob_space = NULL; |
651 | gops->pmu.pmu_populate_loader_cfg = NULL; | 578 | gops->pmu.pmu_populate_loader_cfg = NULL; |
652 | gops->pmu.flcn_populate_bl_dmem_desc = NULL; | 579 | gops->pmu.flcn_populate_bl_dmem_desc = NULL; |
653 | gops->pmu.reset = NULL; | 580 | gops->pmu.reset_engine = gk20a_pmu_engine_reset; |
581 | gops->pmu.is_engine_in_reset = gk20a_pmu_is_engine_in_reset; | ||
654 | } | 582 | } |
655 | 583 | ||
656 | static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, | 584 | static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 8f337855..997a88d2 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -70,9 +70,10 @@ void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, | |||
70 | void *param, u32 handle, u32 status); | 70 | void *param, u32 handle, u32 status); |
71 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, | 71 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, |
72 | struct pmu_pg_stats_data *pg_stat_data); | 72 | struct pmu_pg_stats_data *pg_stat_data); |
73 | int gk20a_pmu_reset(struct gk20a *g); | 73 | bool gk20a_pmu_is_engine_in_reset(struct gk20a *g); |
74 | int gk20a_pmu_engine_reset(struct gk20a *g, bool do_reset); | ||
75 | |||
74 | int pmu_idle(struct nvgpu_pmu *pmu); | 76 | int pmu_idle(struct nvgpu_pmu *pmu); |
75 | int pmu_enable_hw(struct nvgpu_pmu *pmu, bool enable); | ||
76 | 77 | ||
77 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); | 78 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); |
78 | 79 | ||