diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/module.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 77 |
1 files changed, 63 insertions, 14 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index 52f987b2..fe3e4e6f 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c | |||
@@ -137,6 +137,23 @@ void gk20a_idle(struct gk20a *g) | |||
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
140 | /* | ||
141 | * Undoes gk20a_lockout_registers(). | ||
142 | */ | ||
143 | static int gk20a_restore_registers(struct gk20a *g) | ||
144 | { | ||
145 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
146 | |||
147 | l->regs = l->regs_saved; | ||
148 | l->bar1 = l->bar1_saved; | ||
149 | |||
150 | #ifdef CONFIG_TEGRA_19x_GPU | ||
151 | t19x_restore_registers(g); | ||
152 | #endif | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
140 | int gk20a_pm_finalize_poweron(struct device *dev) | 157 | int gk20a_pm_finalize_poweron(struct device *dev) |
141 | { | 158 | { |
142 | struct gk20a *g = get_gk20a(dev); | 159 | struct gk20a *g = get_gk20a(dev); |
@@ -198,6 +215,27 @@ done: | |||
198 | return err; | 215 | return err; |
199 | } | 216 | } |
200 | 217 | ||
218 | /* | ||
219 | * Locks out the driver from accessing GPU registers. This prevents access to | ||
220 | * thse registers after the GPU has been clock or power gated. This should help | ||
221 | * find annoying bugs where register reads and writes are silently dropped | ||
222 | * after the GPU has been turned off. On older chips these reads and writes can | ||
223 | * also lock the entire CPU up. | ||
224 | */ | ||
225 | static int gk20a_lockout_registers(struct gk20a *g) | ||
226 | { | ||
227 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
228 | |||
229 | l->regs = NULL; | ||
230 | l->bar1 = NULL; | ||
231 | |||
232 | #ifdef CONFIG_TEGRA_19x_GPU | ||
233 | t19x_lockout_registers(g); | ||
234 | #endif | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
201 | static int gk20a_pm_prepare_poweroff(struct device *dev) | 239 | static int gk20a_pm_prepare_poweroff(struct device *dev) |
202 | { | 240 | { |
203 | struct gk20a *g = get_gk20a(dev); | 241 | struct gk20a *g = get_gk20a(dev); |
@@ -511,6 +549,8 @@ static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) | |||
511 | 549 | ||
512 | void gk20a_remove_support(struct gk20a *g) | 550 | void gk20a_remove_support(struct gk20a *g) |
513 | { | 551 | { |
552 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
553 | |||
514 | tegra_unregister_idle_unidle(gk20a_do_idle); | 554 | tegra_unregister_idle_unidle(gk20a_do_idle); |
515 | 555 | ||
516 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); | 556 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); |
@@ -535,36 +575,41 @@ void gk20a_remove_support(struct gk20a *g) | |||
535 | 575 | ||
536 | /* free mappings to registers, etc */ | 576 | /* free mappings to registers, etc */ |
537 | 577 | ||
538 | if (g->regs) { | 578 | if (l->regs) { |
539 | iounmap(g->regs); | 579 | iounmap(l->regs); |
540 | g->regs = NULL; | 580 | l->regs = NULL; |
541 | } | 581 | } |
542 | if (g->bar1) { | 582 | if (l->bar1) { |
543 | iounmap(g->bar1); | 583 | iounmap(l->bar1); |
544 | g->bar1 = NULL; | 584 | l->bar1 = NULL; |
545 | } | 585 | } |
586 | |||
587 | #ifdef CONFIG_TEGRA_19x_GPU | ||
588 | t19x_remove_support(g); | ||
589 | #endif | ||
546 | } | 590 | } |
547 | 591 | ||
548 | static int gk20a_init_support(struct platform_device *dev) | 592 | static int gk20a_init_support(struct platform_device *dev) |
549 | { | 593 | { |
550 | int err = 0; | 594 | int err = 0; |
551 | struct gk20a *g = get_gk20a(&dev->dev); | 595 | struct gk20a *g = get_gk20a(&dev->dev); |
596 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
552 | 597 | ||
553 | tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); | 598 | tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); |
554 | 599 | ||
555 | g->regs = gk20a_ioremap_resource(dev, GK20A_BAR0_IORESOURCE_MEM, | 600 | l->regs = gk20a_ioremap_resource(dev, GK20A_BAR0_IORESOURCE_MEM, |
556 | &g->reg_mem); | 601 | &l->reg_mem); |
557 | if (IS_ERR(g->regs)) { | 602 | if (IS_ERR(l->regs)) { |
558 | nvgpu_err(g, "failed to remap gk20a registers"); | 603 | nvgpu_err(g, "failed to remap gk20a registers"); |
559 | err = PTR_ERR(g->regs); | 604 | err = PTR_ERR(l->regs); |
560 | goto fail; | 605 | goto fail; |
561 | } | 606 | } |
562 | 607 | ||
563 | g->bar1 = gk20a_ioremap_resource(dev, GK20A_BAR1_IORESOURCE_MEM, | 608 | l->bar1 = gk20a_ioremap_resource(dev, GK20A_BAR1_IORESOURCE_MEM, |
564 | &g->bar1_mem); | 609 | &l->bar1_mem); |
565 | if (IS_ERR(g->bar1)) { | 610 | if (IS_ERR(l->bar1)) { |
566 | nvgpu_err(g, "failed to remap gk20a bar1"); | 611 | nvgpu_err(g, "failed to remap gk20a bar1"); |
567 | err = PTR_ERR(g->bar1); | 612 | err = PTR_ERR(l->bar1); |
568 | goto fail; | 613 | goto fail; |
569 | } | 614 | } |
570 | 615 | ||
@@ -584,6 +629,10 @@ static int gk20a_init_support(struct platform_device *dev) | |||
584 | goto fail; | 629 | goto fail; |
585 | } | 630 | } |
586 | 631 | ||
632 | #ifdef CONFIG_TEGRA_19x_GPU | ||
633 | t19x_init_support(g); | ||
634 | #endif | ||
635 | |||
587 | return 0; | 636 | return 0; |
588 | 637 | ||
589 | fail: | 638 | fail: |