diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 137 |
1 files changed, 113 insertions, 24 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c index f36b9e32..9568b979 100644 --- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | |||
@@ -10,56 +10,145 @@ | |||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
11 | * more details. | 11 | * more details. |
12 | */ | 12 | */ |
13 | #include <nvgpu/falcon.h> | ||
14 | |||
13 | #include "gk20a/gk20a.h" | 15 | #include "gk20a/gk20a.h" |
14 | 16 | ||
17 | #include <nvgpu/hw/gk20a/hw_falcon_gk20a.h> | ||
18 | |||
19 | static int gk20a_flcn_reset(struct nvgpu_falcon *flcn) | ||
20 | { | ||
21 | struct gk20a *g = flcn->g; | ||
22 | u32 base_addr = flcn->flcn_base; | ||
23 | u32 unit_status = 0; | ||
24 | int status = 0; | ||
25 | |||
26 | if (flcn->flcn_engine_dep_ops.reset_eng) | ||
27 | /* falcon & engine reset */ | ||
28 | status = flcn->flcn_engine_dep_ops.reset_eng(g); | ||
29 | else { | ||
30 | /* do falcon CPU hard reset */ | ||
31 | unit_status = gk20a_readl(g, base_addr + | ||
32 | falcon_falcon_cpuctl_r()); | ||
33 | gk20a_writel(g, base_addr + falcon_falcon_cpuctl_r(), | ||
34 | (unit_status | falcon_falcon_cpuctl_hreset_f(1))); | ||
35 | } | ||
36 | |||
37 | return status; | ||
38 | } | ||
39 | |||
40 | static void gk20a_flcn_set_irq(struct nvgpu_falcon *flcn, bool enable) | ||
41 | { | ||
42 | struct gk20a *g = flcn->g; | ||
43 | u32 base_addr = flcn->flcn_base; | ||
44 | |||
45 | if (!flcn->is_interrupt_enabled) { | ||
46 | nvgpu_warn(g, "Interrupt not supported on flcn 0x%x ", | ||
47 | flcn->flcn_id); | ||
48 | /* Keep interrupt disabled */ | ||
49 | enable = false; | ||
50 | } | ||
51 | |||
52 | if (enable) { | ||
53 | gk20a_writel(g, base_addr + falcon_falcon_irqmset_r(), | ||
54 | flcn->intr_mask); | ||
55 | gk20a_writel(g, base_addr + falcon_falcon_irqdest_r(), | ||
56 | flcn->intr_dest); | ||
57 | } else | ||
58 | gk20a_writel(g, base_addr + falcon_falcon_irqmclr_r(), | ||
59 | 0xffffffff); | ||
60 | } | ||
61 | |||
62 | static bool gk20a_is_falcon_cpu_halted(struct nvgpu_falcon *flcn) | ||
63 | { | ||
64 | struct gk20a *g = flcn->g; | ||
65 | u32 base_addr = flcn->flcn_base; | ||
66 | |||
67 | return (gk20a_readl(g, base_addr + falcon_falcon_cpuctl_r()) & | ||
68 | falcon_falcon_cpuctl_halt_intr_m() ? | ||
69 | true : false); | ||
70 | } | ||
71 | |||
72 | static bool gk20a_is_falcon_idle(struct nvgpu_falcon *flcn) | ||
73 | { | ||
74 | struct gk20a *g = flcn->g; | ||
75 | u32 base_addr = flcn->flcn_base; | ||
76 | u32 unit_status = 0; | ||
77 | bool status = false; | ||
78 | |||
79 | unit_status = gk20a_readl(g, | ||
80 | base_addr + falcon_falcon_idlestate_r()); | ||
81 | |||
82 | if (falcon_falcon_idlestate_falcon_busy_v(unit_status) == 0 && | ||
83 | falcon_falcon_idlestate_ext_busy_v(unit_status) == 0) | ||
84 | status = true; | ||
85 | else | ||
86 | status = false; | ||
87 | |||
88 | return status; | ||
89 | } | ||
90 | |||
91 | static bool gk20a_is_falcon_scrubbing_done(struct nvgpu_falcon *flcn) | ||
92 | { | ||
93 | struct gk20a *g = flcn->g; | ||
94 | u32 base_addr = flcn->flcn_base; | ||
95 | u32 unit_status = 0; | ||
96 | bool status = false; | ||
97 | |||
98 | unit_status = gk20a_readl(g, | ||
99 | base_addr + falcon_falcon_dmactl_r()); | ||
100 | |||
101 | if (unit_status & (falcon_falcon_dmactl_dmem_scrubbing_m() | | ||
102 | falcon_falcon_dmactl_imem_scrubbing_m())) | ||
103 | status = false; | ||
104 | else | ||
105 | status = true; | ||
106 | |||
107 | return status; | ||
108 | } | ||
109 | |||
15 | static void gk20a_falcon_ops(struct nvgpu_falcon *flcn) | 110 | static void gk20a_falcon_ops(struct nvgpu_falcon *flcn) |
16 | { | 111 | { |
17 | struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops; | 112 | struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops; |
18 | struct nvgpu_falcon_version_ops *flcn_vops = &flcn->flcn_vops; | 113 | |
19 | 114 | flcn_ops->reset = gk20a_flcn_reset; | |
20 | flcn_ops->reset = NULL; | 115 | flcn_ops->set_irq = gk20a_flcn_set_irq; |
21 | flcn_ops->enable_irq = NULL; | 116 | flcn_ops->is_falcon_cpu_halted = gk20a_is_falcon_cpu_halted; |
22 | flcn_ops->fbif_transcfg = NULL; | 117 | flcn_ops->is_falcon_idle = gk20a_is_falcon_idle; |
23 | flcn_ops->read_hwcfg = NULL; | 118 | flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; |
24 | flcn_ops->write_hwcfg = NULL; | ||
25 | flcn_ops->copy_from_dmem = NULL; | ||
26 | flcn_ops->copy_to_dmem = NULL; | ||
27 | flcn_ops->dma_copy = NULL; | ||
28 | flcn_ops->mailbox_read = NULL; | ||
29 | flcn_ops->mailbox_write = NULL; | ||
30 | flcn_ops->get_unit_status = NULL; | ||
31 | flcn_ops->dump_falcon_stats = NULL; | ||
32 | |||
33 | flcn_vops->start_cpu_secure = NULL; | ||
34 | flcn_vops->write_dmatrfbase = NULL; | ||
35 | } | 119 | } |
36 | 120 | ||
37 | static void gk20a_falcon_hal_sw_init(struct nvgpu_falcon *flcn) | 121 | static void gk20a_falcon_hal_sw_init(struct nvgpu_falcon *flcn) |
38 | { | 122 | { |
39 | struct gk20a *g = flcn->g; | 123 | struct gk20a *g = flcn->g; |
40 | 124 | ||
41 | |||
42 | switch (flcn->flcn_id) { | 125 | switch (flcn->flcn_id) { |
43 | case FALCON_ID_PMU: | 126 | case FALCON_ID_PMU: |
44 | flcn->flcn_base = FALCON_PWR_BASE; | 127 | flcn->flcn_base = FALCON_PWR_BASE; |
128 | flcn->is_falcon_supported = true; | ||
129 | flcn->is_interrupt_enabled = true; | ||
45 | break; | 130 | break; |
46 | case FALCON_ID_SEC2: | ||
47 | flcn->flcn_base = FALCON_SEC_BASE; | ||
48 | break; | ||
49 | case FALCON_ID_FECS: | 131 | case FALCON_ID_FECS: |
50 | flcn->flcn_base = FALCON_FECS_BASE; | 132 | flcn->flcn_base = FALCON_FECS_BASE; |
133 | flcn->is_falcon_supported = true; | ||
134 | flcn->is_interrupt_enabled = false; | ||
51 | break; | 135 | break; |
52 | case FALCON_ID_GPCCS: | 136 | case FALCON_ID_GPCCS: |
53 | flcn->flcn_base = FALCON_GPCCS_BASE; | 137 | flcn->flcn_base = FALCON_GPCCS_BASE; |
138 | flcn->is_falcon_supported = true; | ||
139 | flcn->is_interrupt_enabled = false; | ||
54 | break; | 140 | break; |
55 | default: | 141 | default: |
142 | flcn->is_falcon_supported = false; | ||
56 | nvgpu_err(g, "Invalid flcn request"); | 143 | nvgpu_err(g, "Invalid flcn request"); |
57 | break; | 144 | break; |
58 | } | 145 | } |
59 | 146 | ||
60 | nvgpu_mutex_init(&flcn->copy_lock); | 147 | if (flcn->is_falcon_supported) { |
61 | 148 | gk20a_falcon_ops(flcn); | |
62 | gk20a_falcon_ops(flcn); | 149 | } else |
150 | nvgpu_info(g, "flcn-Id 0x%x not supported on current chip", | ||
151 | flcn->flcn_id); | ||
63 | } | 152 | } |
64 | 153 | ||
65 | void gk20a_falcon_init_hal(struct gpu_ops *gops) | 154 | void gk20a_falcon_init_hal(struct gpu_ops *gops) |