diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2014-10-27 05:03:00 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:11:56 -0400 |
commit | 8371833f4273c2d4a6f923eb3270b4ab93967743 (patch) | |
tree | 92faf9b7bc19bdc14a5c46b25f3ab7acc6cf65e3 /drivers/gpu/nvgpu/gk20a/mc_gk20a.c | |
parent | eb690cb391ca0578a2c086eff5085f16c32f651e (diff) |
gpu: nvgpu: Per-chip interrupt processing
Move accesses to MC registers under HAL so that they can be
reimplemented per chip.
Do chip detection and HAL initialization only once.
Bug 1567274
Change-Id: I20bf2f439d267d284bfd536f1a1dfb5d5a2dce4c
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/590385
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mc_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mc_gk20a.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c new file mode 100644 index 00000000..53701605 --- /dev/null +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * GK20A memory interface | ||
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 "gk20a.h" | ||
19 | #include "mc_gk20a.h" | ||
20 | #include "hw_mc_gk20a.h" | ||
21 | |||
22 | irqreturn_t mc_gk20a_isr_stall(struct gk20a *g) | ||
23 | { | ||
24 | u32 mc_intr_0; | ||
25 | |||
26 | if (!g->power_on) | ||
27 | return IRQ_NONE; | ||
28 | |||
29 | /* not from gpu when sharing irq with others */ | ||
30 | mc_intr_0 = gk20a_readl(g, mc_intr_0_r()); | ||
31 | if (unlikely(!mc_intr_0)) | ||
32 | return IRQ_NONE; | ||
33 | |||
34 | gk20a_writel(g, mc_intr_en_0_r(), | ||
35 | mc_intr_en_0_inta_disabled_f()); | ||
36 | |||
37 | /* flush previous write */ | ||
38 | gk20a_readl(g, mc_intr_en_0_r()); | ||
39 | |||
40 | return IRQ_WAKE_THREAD; | ||
41 | } | ||
42 | |||
43 | irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) | ||
44 | { | ||
45 | u32 mc_intr_1; | ||
46 | |||
47 | if (!g->power_on) | ||
48 | return IRQ_NONE; | ||
49 | |||
50 | /* not from gpu when sharing irq with others */ | ||
51 | mc_intr_1 = gk20a_readl(g, mc_intr_1_r()); | ||
52 | if (unlikely(!mc_intr_1)) | ||
53 | return IRQ_NONE; | ||
54 | |||
55 | gk20a_writel(g, mc_intr_en_1_r(), | ||
56 | mc_intr_en_1_inta_disabled_f()); | ||
57 | |||
58 | /* flush previous write */ | ||
59 | gk20a_readl(g, mc_intr_en_1_r()); | ||
60 | |||
61 | return IRQ_WAKE_THREAD; | ||
62 | } | ||
63 | |||
64 | irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) | ||
65 | { | ||
66 | u32 mc_intr_0; | ||
67 | |||
68 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | ||
69 | |||
70 | mc_intr_0 = gk20a_readl(g, mc_intr_0_r()); | ||
71 | |||
72 | gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); | ||
73 | |||
74 | if (mc_intr_0 & mc_intr_0_pgraph_pending_f()) | ||
75 | gr_gk20a_elpg_protected_call(g, gk20a_gr_isr(g)); | ||
76 | if (mc_intr_0 & mc_intr_0_pfifo_pending_f()) | ||
77 | gk20a_fifo_isr(g); | ||
78 | if (mc_intr_0 & mc_intr_0_pmu_pending_f()) | ||
79 | gk20a_pmu_isr(g); | ||
80 | if (mc_intr_0 & mc_intr_0_priv_ring_pending_f()) | ||
81 | gk20a_priv_ring_isr(g); | ||
82 | if (mc_intr_0 & mc_intr_0_ltc_pending_f()) | ||
83 | g->ops.ltc.isr(g); | ||
84 | if (mc_intr_0 & mc_intr_0_pbus_pending_f()) | ||
85 | gk20a_pbus_isr(g); | ||
86 | |||
87 | gk20a_writel(g, mc_intr_en_0_r(), | ||
88 | mc_intr_en_0_inta_hardware_f()); | ||
89 | |||
90 | /* flush previous write */ | ||
91 | gk20a_readl(g, mc_intr_en_0_r()); | ||
92 | |||
93 | return IRQ_HANDLED; | ||
94 | } | ||
95 | |||
96 | irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g) | ||
97 | { | ||
98 | u32 mc_intr_1; | ||
99 | |||
100 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | ||
101 | |||
102 | mc_intr_1 = gk20a_readl(g, mc_intr_1_r()); | ||
103 | |||
104 | gk20a_dbg(gpu_dbg_intr, "non-stall intr %08x\n", mc_intr_1); | ||
105 | |||
106 | if (mc_intr_1 & mc_intr_0_pfifo_pending_f()) | ||
107 | gk20a_fifo_nonstall_isr(g); | ||
108 | if (mc_intr_1 & mc_intr_0_pgraph_pending_f()) | ||
109 | gk20a_gr_nonstall_isr(g); | ||
110 | |||
111 | gk20a_writel(g, mc_intr_en_1_r(), | ||
112 | mc_intr_en_1_inta_hardware_f()); | ||
113 | |||
114 | /* flush previous write */ | ||
115 | gk20a_readl(g, mc_intr_en_1_r()); | ||
116 | |||
117 | return IRQ_HANDLED; | ||
118 | } | ||
119 | |||
120 | void mc_gk20a_intr_enable(struct gk20a *g) | ||
121 | { | ||
122 | gk20a_writel(g, mc_intr_en_1_r(), | ||
123 | mc_intr_en_1_inta_hardware_f()); | ||
124 | |||
125 | gk20a_writel(g, mc_intr_en_0_r(), | ||
126 | mc_intr_en_0_inta_hardware_f()); | ||
127 | } | ||
128 | |||
129 | void gk20a_init_mc(struct gpu_ops *gops) | ||
130 | { | ||
131 | gops->mc.intr_enable = mc_gk20a_intr_enable; | ||
132 | gops->mc.isr_stall = mc_gk20a_isr_stall; | ||
133 | gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; | ||
134 | gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall; | ||
135 | gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; | ||
136 | } | ||