summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2016-02-29 05:34:16 -0500
committerDeepak Nibade <dnibade@nvidia.com>2016-03-08 03:28:17 -0500
commit9a8a533e18d81964df148c225773eea2b76039e1 (patch)
tree0ba0950ce1a489d6c62f98bad1ab6b7781ac07e1 /drivers/gpu
parent5672f8015e9fecf42a6374cf5990a88abd279d68 (diff)
gpu: host1x: add T186 support
Add host1x05 version and fill in the h/w details in host1x05_info Add all the hardware accessors for T186 (channel, sync, uclass accessors) Add hardware support files for host1x channel, syncpoints, cdma, pushbuffer, interrupt, and debug support Keep gather filter disabled Things working with this : - cdma operations - basic channel job submit path - syncpoint support - syncpoint interrupt mechanism - debug dump With this support, below tests pass for VIC client $nvrm_channel channel_Basic $nvrm_channel --module=vic Bug 1704301 Change-Id: I7d97560cb1e3a57733fa0853936b0783c71b7060 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1021434 GVS: Gerrit_Virtual_Submit Reviewed-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/host1x/Makefile8
-rw-r--r--drivers/gpu/host1x/dev_t186.c40
-rw-r--r--drivers/gpu/host1x/dev_t186.h34
-rw-r--r--drivers/gpu/host1x/hw/cdma_hw_t186.c340
-rw-r--r--drivers/gpu/host1x/hw/channel_hw_t186.c297
-rw-r--r--drivers/gpu/host1x/hw/debug_hw_t186.c288
-rw-r--r--drivers/gpu/host1x/hw/host1x05.c40
-rw-r--r--drivers/gpu/host1x/hw/host1x05.h24
-rw-r--r--drivers/gpu/host1x/hw/host1x05_hardware.h128
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x05_channel.h169
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x05_sync.h321
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x05_uclass.h157
-rw-r--r--drivers/gpu/host1x/hw/intr_hw_t186.c247
-rw-r--r--drivers/gpu/host1x/hw/syncpt_hw_t186.c126
14 files changed, 2219 insertions, 0 deletions
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
new file mode 100644
index 000000000..9c8c6467b
--- /dev/null
+++ b/drivers/gpu/host1x/Makefile
@@ -0,0 +1,8 @@
1ccflags-y += -Idrivers/gpu/host1x
2ccflags-y += -I../kernel-t18x/drivers/gpu/host1x
3
4host1x-t186-y = \
5 dev_t186.o \
6 hw/host1x05.o
7
8obj-$(CONFIG_TEGRA_HOST1X) += host1x-t186.o
diff --git a/drivers/gpu/host1x/dev_t186.c b/drivers/gpu/host1x/dev_t186.c
new file mode 100644
index 000000000..e4d148760
--- /dev/null
+++ b/drivers/gpu/host1x/dev_t186.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "dev.h"
18#include "dev_t186.h"
19
20#include "hw/host1x05.h"
21
22struct host1x_info host1x05_info = {
23 .nb_channels = 63,
24 .nb_pts = 576,
25 .nb_mlocks = 24,
26 .nb_bases = 16,
27 .init = host1x05_init,
28 .sync_offset = 0x0,
29 .gather_filter_enabled = false,
30};
31
32void host1x_writel(struct host1x *host1x, u32 v, u32 r)
33{
34 writel(v, host1x->regs + r);
35}
36
37u32 host1x_readl(struct host1x *host1x, u32 r)
38{
39 return readl(host1x->regs + r);
40}
diff --git a/drivers/gpu/host1x/dev_t186.h b/drivers/gpu/host1x/dev_t186.h
new file mode 100644
index 000000000..be9726e88
--- /dev/null
+++ b/drivers/gpu/host1x/dev_t186.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef HOST1X_DEV_T186_H
18#define HOST1X_DEV_T186_H
19
20#include "dev.h"
21
22extern struct host1x_info host1x05_info;
23
24void host1x_writel(struct host1x *host1x, u32 v, u32 r);
25u32 host1x_readl(struct host1x *host1x, u32 r);
26
27static inline void host1x_hw_sync_get_mutex_owner(struct host1x *host,
28 struct host1x_syncpt *sp,
29 unsigned int mutex_id, bool *cpu, bool *ch,
30 unsigned int *chid)
31{
32 host->syncpt_op->get_mutex_owner(sp, mutex_id, cpu, ch, chid);
33}
34#endif
diff --git a/drivers/gpu/host1x/hw/cdma_hw_t186.c b/drivers/gpu/host1x/hw/cdma_hw_t186.c
new file mode 100644
index 000000000..e903f3e8b
--- /dev/null
+++ b/drivers/gpu/host1x/hw/cdma_hw_t186.c
@@ -0,0 +1,340 @@
1/*
2 * Tegra host1x Command DMA
3 *
4 * Copyright (c) 2016, 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 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/slab.h>
20#include <linux/scatterlist.h>
21#include <linux/dma-mapping.h>
22
23#include "cdma.h"
24#include "channel.h"
25#include "dev.h"
26#include "debug.h"
27
28/*
29 * Put the restart at the end of pushbuffer memory
30 */
31static void push_buffer_init(struct push_buffer *pb)
32{
33 *(u32 *)(pb->mapped + pb->size_bytes) = host1x_opcode_restart(0);
34}
35
36/*
37 * Increment timedout buffer's syncpt via CPU.
38 */
39static void cdma_timeout_handle(struct host1x_cdma *cdma, u32 getptr,
40 u32 nr_slots)
41{
42 struct host1x *host1x = cdma_to_host1x(cdma);
43 struct push_buffer *pb = &cdma->push_buffer;
44
45 /* NOP all the PB slots */
46 while (nr_slots--) {
47 u32 *p = (u32 *)(pb->mapped + getptr);
48 *(p++) = HOST1X_OPCODE_NOP;
49 *(p++) = HOST1X_OPCODE_NOP;
50 dev_dbg(host1x->dev, "%s: NOP at %pad+%#x\n", __func__,
51 &pb->phys, getptr);
52 getptr = (getptr + 8) & (pb->size_bytes - 1);
53 }
54 wmb();
55}
56
57/*
58 * Start channel DMA
59 */
60static void cdma_start(struct host1x_cdma *cdma)
61{
62 struct host1x_channel *ch = cdma_to_channel(cdma);
63
64 if (cdma->running)
65 return;
66
67 cdma->last_pos = cdma->push_buffer.pos;
68
69 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
70 HOST1X_CHANNEL_DMACTRL);
71
72 /* set base, put and end pointer */
73 host1x_ch_writel(ch, cdma->push_buffer.phys, HOST1X_CHANNEL_DMASTART);
74 host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT);
75 host1x_ch_writel(ch, cdma->push_buffer.phys +
76 cdma->push_buffer.size_bytes + 4,
77 HOST1X_CHANNEL_DMAEND);
78
79 /* reset GET */
80 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP |
81 HOST1X_CHANNEL_DMACTRL_DMAGETRST |
82 HOST1X_CHANNEL_DMACTRL_DMAINITGET,
83 HOST1X_CHANNEL_DMACTRL);
84
85 host1x_channel_enable_gather_filter(ch);
86
87 /* start the command DMA */
88 host1x_ch_writel(ch, 0, HOST1X_CHANNEL_DMACTRL);
89
90 cdma->running = true;
91}
92
93/*
94 * Similar to cdma_start(), but rather than starting from an idle
95 * state (where DMA GET is set to DMA PUT), on a timeout we restore
96 * DMA GET from an explicit value (so DMA may again be pending).
97 */
98static void cdma_timeout_restart(struct host1x_cdma *cdma, u32 getptr)
99{
100 struct host1x *host1x = cdma_to_host1x(cdma);
101 struct host1x_channel *ch = cdma_to_channel(cdma);
102
103 if (cdma->running)
104 return;
105
106 cdma->last_pos = cdma->push_buffer.pos;
107
108 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
109 HOST1X_CHANNEL_DMACTRL);
110
111 /* set base, end pointer (all of memory) */
112 host1x_ch_writel(ch, cdma->push_buffer.phys, HOST1X_CHANNEL_DMASTART);
113 host1x_ch_writel(ch, cdma->push_buffer.phys +
114 cdma->push_buffer.size_bytes,
115 HOST1X_CHANNEL_DMAEND);
116
117 /* set GET, by loading the value in PUT (then reset GET) */
118 host1x_ch_writel(ch, getptr, HOST1X_CHANNEL_DMAPUT);
119 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP |
120 HOST1X_CHANNEL_DMACTRL_DMAGETRST |
121 HOST1X_CHANNEL_DMACTRL_DMAINITGET,
122 HOST1X_CHANNEL_DMACTRL);
123
124 dev_dbg(host1x->dev,
125 "%s: DMA GET 0x%x, PUT HW 0x%x / shadow 0x%x\n", __func__,
126 host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET),
127 host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT),
128 cdma->last_pos);
129
130 /* deassert GET reset and set PUT */
131 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
132 HOST1X_CHANNEL_DMACTRL);
133 host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT);
134
135 host1x_channel_enable_gather_filter(ch);
136
137 /* start the command DMA */
138 host1x_ch_writel(ch, 0, HOST1X_CHANNEL_DMACTRL);
139
140 cdma->running = true;
141}
142
143/*
144 * Kick channel DMA into action by writing its PUT offset (if it has changed)
145 */
146static void cdma_flush(struct host1x_cdma *cdma)
147{
148 struct host1x_channel *ch = cdma_to_channel(cdma);
149
150 if (cdma->push_buffer.pos != cdma->last_pos) {
151 host1x_ch_writel(ch, cdma->push_buffer.pos,
152 HOST1X_CHANNEL_DMAPUT);
153 cdma->last_pos = cdma->push_buffer.pos;
154 }
155}
156
157static void cdma_stop(struct host1x_cdma *cdma)
158{
159 struct host1x_channel *ch = cdma_to_channel(cdma);
160
161 mutex_lock(&cdma->lock);
162 if (cdma->running) {
163 host1x_cdma_wait_locked(cdma, CDMA_EVENT_SYNC_QUEUE_EMPTY);
164 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
165 HOST1X_CHANNEL_DMACTRL);
166 cdma->running = false;
167 }
168 mutex_unlock(&cdma->lock);
169}
170
171/*
172 * Stops both channel's command processor and CDMA immediately.
173 * Also, tears down the channel and resets corresponding module.
174 */
175static void cdma_freeze(struct host1x_cdma *cdma)
176{
177 struct host1x *host = cdma_to_host1x(cdma);
178 struct host1x_channel *ch = cdma_to_channel(cdma);
179 u32 cmdproc_stop;
180
181 if (cdma->torndown && !cdma->running) {
182 dev_warn(host->dev, "Already torn down\n");
183 return;
184 }
185
186 dev_dbg(host->dev, "freezing channel (id %d)\n", ch->id);
187
188 cmdproc_stop = host1x_ch_readl(ch, HOST1X_SYNC_CMDPROC_STOP);
189 cmdproc_stop |= BIT(0);
190 host1x_ch_writel(ch, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
191
192 dev_dbg(host->dev, "%s: DMA GET 0x%x, PUT HW 0x%x / shadow 0x%x\n",
193 __func__, host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET),
194 host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT),
195 cdma->last_pos);
196
197 host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
198 HOST1X_CHANNEL_DMACTRL);
199
200 host1x_ch_writel(ch, BIT(0), HOST1X_SYNC_CH_TEARDOWN);
201
202 cdma->running = false;
203 cdma->torndown = true;
204}
205
206static void cdma_resume(struct host1x_cdma *cdma, u32 getptr)
207{
208 struct host1x *host1x = cdma_to_host1x(cdma);
209 struct host1x_channel *ch = cdma_to_channel(cdma);
210 u32 cmdproc_stop;
211
212 dev_dbg(host1x->dev,
213 "resuming channel (id %d, DMAGET restart = 0x%x)\n",
214 ch->id, getptr);
215
216 cmdproc_stop = host1x_ch_readl(ch, HOST1X_SYNC_CMDPROC_STOP);
217 cmdproc_stop &= ~(BIT(0));
218 host1x_ch_writel(ch, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
219
220 cdma->torndown = false;
221 cdma_timeout_restart(cdma, getptr);
222}
223
224/*
225 * If this timeout fires, it indicates the current sync_queue entry has
226 * exceeded its TTL and the userctx should be timed out and remaining
227 * submits already issued cleaned up (future submits return an error).
228 */
229static void cdma_timeout_handler(struct work_struct *work)
230{
231 struct host1x_cdma *cdma;
232 struct host1x *host1x;
233 struct host1x_channel *ch;
234 bool has_timedout = 0;
235
236 u32 prev_cmdproc, cmdproc_stop;
237
238 unsigned int i;
239
240 cdma = container_of(to_delayed_work(work), struct host1x_cdma,
241 timeout.wq);
242 host1x = cdma_to_host1x(cdma);
243 ch = cdma_to_channel(cdma);
244
245 host1x_debug_dump(cdma_to_host1x(cdma));
246
247 mutex_lock(&cdma->lock);
248
249 if (!cdma->timeout.client) {
250 dev_dbg(host1x->dev,
251 "cdma_timeout: expired, but has no clientid\n");
252 mutex_unlock(&cdma->lock);
253 return;
254 }
255
256 /* stop processing to get a clean snapshot */
257 prev_cmdproc = host1x_ch_readl(ch, HOST1X_SYNC_CMDPROC_STOP);
258 cmdproc_stop = prev_cmdproc | BIT(0);
259 host1x_ch_writel(ch, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
260
261 dev_dbg(host1x->dev, "cdma_timeout: cmdproc was 0x%x is 0x%x\n",
262 prev_cmdproc, cmdproc_stop);
263
264 for (i = 0; i < cdma->timeout.num_syncpts; ++i) {
265 u32 id = cdma->timeout.syncpts[i].id;
266 u32 end = cdma->timeout.syncpts[i].end;
267 struct host1x_syncpt *syncpt = host1x_syncpt_get(host1x, id);
268
269 host1x_syncpt_load(syncpt);
270
271 has_timedout = !host1x_syncpt_is_expired(syncpt, end);
272 if (has_timedout)
273 break;
274 }
275
276 /* has buffer actually completed? */
277 if (!has_timedout) {
278 dev_dbg(host1x->dev,
279 "cdma_timeout: expired, but buffer had completed\n");
280 /* restore */
281 cmdproc_stop = prev_cmdproc & ~(BIT(0));
282 host1x_ch_writel(ch, cmdproc_stop,
283 HOST1X_SYNC_CMDPROC_STOP);
284 mutex_unlock(&cdma->lock);
285 return;
286 }
287
288 for (i = 0; i < cdma->timeout.num_syncpts; ++i) {
289 u32 id = cdma->timeout.syncpts[i].id;
290 struct host1x_syncpt *syncpt = host1x_syncpt_get(host1x, id);
291 u32 syncpt_val = host1x_syncpt_read_min(syncpt);
292
293 dev_warn(host1x->dev, "%s: timeout: %d (%s), HW thresh %d, done %d\n",
294 __func__, syncpt->id, syncpt->name,
295 syncpt_val, syncpt_val);
296 }
297
298 /* stop HW, resetting channel/module */
299 host1x_hw_cdma_freeze(host1x, cdma);
300
301 host1x_cdma_update_sync_queue(cdma, ch->dev);
302 mutex_unlock(&cdma->lock);
303}
304
305/*
306 * Init timeout resources
307 */
308static int cdma_timeout_init(struct host1x_cdma *cdma)
309{
310 INIT_DELAYED_WORK(&cdma->timeout.wq, cdma_timeout_handler);
311 cdma->timeout.initialized = true;
312
313 return 0;
314}
315
316/*
317 * Clean up timeout resources
318 */
319static void cdma_timeout_destroy(struct host1x_cdma *cdma)
320{
321 if (cdma->timeout.initialized)
322 cancel_delayed_work(&cdma->timeout.wq);
323 cdma->timeout.initialized = false;
324}
325
326static const struct host1x_cdma_ops host1x_cdma_t186_ops = {
327 .start = cdma_start,
328 .stop = cdma_stop,
329 .flush = cdma_flush,
330
331 .timeout_init = cdma_timeout_init,
332 .timeout_destroy = cdma_timeout_destroy,
333 .freeze = cdma_freeze,
334 .resume = cdma_resume,
335 .timeout_handle = cdma_timeout_handle,
336};
337
338static const struct host1x_pushbuffer_ops host1x_pushbuffer_t186_ops = {
339 .init = push_buffer_init,
340};
diff --git a/drivers/gpu/host1x/hw/channel_hw_t186.c b/drivers/gpu/host1x/hw/channel_hw_t186.c
new file mode 100644
index 000000000..2b90ba638
--- /dev/null
+++ b/drivers/gpu/host1x/hw/channel_hw_t186.c
@@ -0,0 +1,297 @@
1/*
2 * Tegra host1x Channel
3 *
4 * Copyright (C) 2016 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 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/host1x.h>
20#include <linux/slab.h>
21#include <linux/iommu.h>
22
23#include <trace/events/host1x.h>
24
25#include "dev_t186.h"
26#include "channel.h"
27#include "intr.h"
28#include "job.h"
29
30#define TRACE_MAX_LENGTH 128U
31
32static void trace_write_gather(struct host1x_cdma *cdma, struct host1x_bo *bo,
33 u32 offset, u32 words)
34{
35 struct device *dev = cdma_to_channel(cdma)->dev;
36 void *mem = NULL;
37
38 if (host1x_debug_trace_cmdbuf)
39 mem = host1x_bo_mmap(bo);
40
41 if (mem) {
42 u32 i;
43 /*
44 * Write in batches of 128 as there seems to be a limit
45 * of how much you can output to ftrace at once.
46 */
47 for (i = 0; i < words; i += TRACE_MAX_LENGTH) {
48 u32 num_words = min(words - i, TRACE_MAX_LENGTH);
49 u32 next_offset = offset + i * sizeof(u32);
50
51 trace_host1x_cdma_push_gather(dev_name(dev), bo,
52 num_words,
53 next_offset,
54 mem);
55 }
56
57 host1x_bo_munmap(bo, mem);
58 }
59}
60
61static void channel_push_wait(struct host1x_channel *channel,
62 u32 id, u32 thresh)
63{
64 host1x_cdma_push(&channel->cdma,
65 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
66 HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32, 1),
67 thresh);
68 host1x_cdma_push(&channel->cdma,
69 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
70 HOST1X_UCLASS_WAIT_SYNCPT_32, 1),
71 id);
72}
73
74static inline void serialize(struct host1x_job *job)
75{
76 struct host1x_channel *ch = job->channel;
77 struct host1x *host = dev_get_drvdata(ch->dev->parent);
78 unsigned int i;
79
80 for (i = 0; i < job->num_syncpts; ++i) {
81 u32 syncpt_id = job->syncpts[i].id;
82 struct host1x_syncpt *syncpt =
83 host1x_syncpt_get(host, syncpt_id);
84
85 /*
86 * Force serialization by inserting a host wait for the
87 * previous job to finish before this one can commence.
88 */
89 channel_push_wait(ch, syncpt_id, host1x_syncpt_read_max(syncpt));
90 }
91}
92
93static void add_sync_waits(struct host1x_job *job)
94{
95 struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
96 unsigned int i;
97
98 for (i = 0; i < job->num_gathers; i++) {
99 struct host1x_job_gather *g = &job->gathers[i];
100
101 if (g->pre_fence)
102 host1x_sync_fence_wait(g->pre_fence, host,
103 job->channel);
104 }
105}
106
107static void submit_gathers(struct host1x_job *job)
108{
109 struct host1x_cdma *cdma = &job->channel->cdma;
110 unsigned int i;
111 u32 cur_class = 0;
112
113 cur_class = HOST1X_CLASS_HOST1X;
114 host1x_cdma_push(cdma,
115 host1x_opcode_acquire_mlock(cur_class),
116 host1x_opcode_setclass(cur_class, 0, 0));
117
118 add_sync_waits(job);
119
120 for (i = 0; i < job->num_gathers; i++) {
121 struct host1x_job_gather *g = &job->gathers[i];
122 u32 op1 = host1x_opcode_gather(g->words);
123 u32 op2 = g->base + g->offset;
124
125 /* add a setclass for modules that require it */
126 if (cur_class != g->class_id) {
127 if (cur_class)
128 host1x_cdma_push(cdma,
129 HOST1X_OPCODE_NOP,
130 host1x_opcode_release_mlock(cur_class));
131
132 host1x_cdma_push(cdma,
133 host1x_opcode_acquire_mlock(g->class_id),
134 host1x_opcode_setclass(g->class_id, 0, 0));
135 cur_class = g->class_id;
136 }
137
138 trace_write_gather(cdma, g->bo, g->offset, op1 & 0xffff);
139 host1x_cdma_push(cdma, op1, op2);
140 }
141
142 if (job->serialize)
143 serialize(job);
144
145 if (cur_class)
146 host1x_cdma_push(cdma,
147 HOST1X_OPCODE_NOP,
148 host1x_opcode_release_mlock(cur_class));
149}
150
151static inline void synchronize_syncpt_base(struct host1x_job *job)
152{
153 struct host1x_channel *ch = job->channel;
154 struct host1x *host = dev_get_drvdata(ch->dev->parent);
155 unsigned int i;
156
157 for (i = 0; i < job->num_syncpts; ++i) {
158 u32 syncpt_id = job->syncpts[i].id;
159 struct host1x_syncpt *syncpt =
160 host1x_syncpt_get(host, syncpt_id);
161 u32 base_id, value;
162
163 if (!syncpt->base)
164 continue;
165
166 value = host1x_syncpt_read_max(syncpt);
167 base_id = syncpt->base->id;
168
169 host1x_cdma_push(&job->channel->cdma,
170 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
171 HOST1X_UCLASS_LOAD_SYNCPT_BASE, 1),
172 HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(base_id) |
173 HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(value));
174 }
175}
176
177static int channel_submit(struct host1x_job *job)
178{
179 struct host1x_channel *ch = job->channel;
180 struct host1x_syncpt *syncpt;
181 u32 prev_max = 0;
182 int err;
183 struct host1x_waitlist *completed_waiter[job->num_syncpts];
184 struct host1x *host = dev_get_drvdata(ch->dev->parent);
185 unsigned int i;
186 int streamid = 0;
187
188 trace_host1x_channel_submit(dev_name(ch->dev),
189 job->num_gathers, job->num_relocs,
190 job->num_waitchk, job->syncpts[0].id,
191 job->syncpts[0].incrs);
192
193 /* before error checks, return current max */
194 syncpt = host1x_syncpt_get(host, job->syncpts[0].id);
195 prev_max = host1x_syncpt_read_max(syncpt);
196
197 /* get submit lock */
198 err = mutex_lock_interruptible(&ch->submitlock);
199 if (err)
200 goto error;
201
202 for (i = 0; i < job->num_syncpts; i++) {
203 completed_waiter[i] = kzalloc(sizeof(*completed_waiter[i]),
204 GFP_KERNEL);
205 if (!completed_waiter[i]) {
206 mutex_unlock(&ch->submitlock);
207 err = -ENOMEM;
208 goto error;
209 }
210 }
211
212 streamid = iommu_get_hwid(host->dev->archdata.iommu, host->dev, 0);
213 if (streamid >= 0)
214 host1x_ch_writel(ch, streamid, HOST1X_CHANNEL_SMMU_STREAMID);
215
216 /* begin a CDMA submit */
217 err = host1x_cdma_begin(&ch->cdma, job);
218 if (err) {
219 mutex_unlock(&ch->submitlock);
220 goto error;
221 }
222
223 /* Synchronize base register to allow using it for relative waiting */
224 synchronize_syncpt_base(job);
225
226 /* Increment syncpoint maximum values */
227 for (i = 0; i < job->num_syncpts; ++i) {
228 u32 id;
229 u32 incrs;
230
231 id = job->syncpts[i].id;
232 incrs = job->syncpts[i].incrs;
233 syncpt = host1x_syncpt_get(host, id);
234 job->syncpts[i].end = host1x_syncpt_incr_max(syncpt, incrs);
235 }
236
237 submit_gathers(job);
238
239 /* end CDMA submit & stash pinned hMems into sync queue */
240 host1x_cdma_end(&ch->cdma, job);
241
242 trace_host1x_channel_submitted(dev_name(ch->dev), prev_max,
243 job->syncpts[0].end);
244
245 /* schedule submit complete interrupts */
246 for (i = 0; i < job->num_syncpts; ++i) {
247 u32 syncpt_id = job->syncpts[i].id;
248 u32 syncpt_end = job->syncpts[i].end;
249
250 err = host1x_intr_add_action(host, syncpt_id, syncpt_end,
251 HOST1X_INTR_ACTION_SUBMIT_COMPLETE,
252 ch, completed_waiter[i], NULL);
253 completed_waiter[i] = NULL;
254 WARN(err, "Failed to set submit complete interrupt");
255 }
256
257 mutex_unlock(&ch->submitlock);
258
259 return 0;
260
261error:
262 for (i = 0; i < job->num_syncpts; i++)
263 kfree(completed_waiter[i]);
264 return err;
265}
266
267static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev,
268 unsigned int index)
269{
270 ch->id = index;
271 mutex_init(&ch->reflock);
272 mutex_init(&ch->submitlock);
273
274 ch->regs = dev->regs + (HOST1X_CHANNEL_CH_APERTURE_START +
275 index * HOST1X_CHANNEL_CH_APERTURE_SIZE);
276 return 0;
277}
278
279static void channel_enable_gather_filter(struct host1x_channel *ch)
280{
281 struct host1x *host = dev_get_drvdata(ch->dev->parent);
282 u32 val;
283
284 val = host1x_readl(host, HOST1X_CHANNEL_FILTER_GBUFFER
285 + BIT_WORD(ch->id) * sizeof(u32));
286
287 host1x_writel(host, val | BIT_MASK(ch->id),
288 HOST1X_CHANNEL_FILTER_GBUFFER
289 + BIT_WORD(ch->id) * sizeof(u32));
290}
291
292static const struct host1x_channel_ops host1x_channel_t186_ops = {
293 .init = host1x_channel_init,
294 .submit = channel_submit,
295 .push_wait = channel_push_wait,
296 .enable_gather_filter = channel_enable_gather_filter,
297};
diff --git a/drivers/gpu/host1x/hw/debug_hw_t186.c b/drivers/gpu/host1x/hw/debug_hw_t186.c
new file mode 100644
index 000000000..d6111668e
--- /dev/null
+++ b/drivers/gpu/host1x/hw/debug_hw_t186.c
@@ -0,0 +1,288 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 * Author: Erik Gilling <konkers@android.com>
4 *
5 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include "dev.h"
19#include "debug.h"
20#include "cdma.h"
21#include "channel.h"
22
23#define HOST1X_DEBUG_MAX_PAGE_OFFSET 102400
24
25enum {
26 HOST1X_OPCODE_SETCLASS = 0x00,
27 HOST1X_OPCODE_INCR = 0x01,
28 HOST1X_OPCODE_NONINCR = 0x02,
29 HOST1X_OPCODE_MASK = 0x03,
30 HOST1X_OPCODE_IMM = 0x04,
31 HOST1X_OPCODE_RESTART = 0x05,
32 HOST1X_OPCODE_GATHER = 0x06,
33 HOST1X_OPCODE_EXTEND = 0x0e,
34};
35
36enum {
37 HOST1X_OPCODE_EXTEND_ACQUIRE_MLOCK = 0x00,
38 HOST1X_OPCODE_EXTEND_RELEASE_MLOCK = 0x01,
39};
40
41static unsigned int show_channel_command(struct output *o, u32 val)
42{
43 unsigned mask;
44 unsigned subop;
45
46 switch (val >> 28) {
47 case HOST1X_OPCODE_SETCLASS:
48 mask = val & 0x3f;
49 if (mask) {
50 host1x_debug_output(o, "SETCL(class=%03x, offset=%03x, mask=%02x, [",
51 val >> 6 & 0x3ff,
52 val >> 16 & 0xfff, mask);
53 return hweight8(mask);
54 } else {
55 host1x_debug_output(o, "SETCL(class=%03x)\n",
56 val >> 6 & 0x3ff);
57 return 0;
58 }
59
60 case HOST1X_OPCODE_INCR:
61 host1x_debug_output(o, "INCR(offset=%03x, [",
62 val >> 16 & 0xfff);
63 return val & 0xffff;
64
65 case HOST1X_OPCODE_NONINCR:
66 host1x_debug_output(o, "NONINCR(offset=%03x, [",
67 val >> 16 & 0xfff);
68 return val & 0xffff;
69
70 case HOST1X_OPCODE_MASK:
71 mask = val & 0xffff;
72 host1x_debug_output(o, "MASK(offset=%03x, mask=%03x, [",
73 val >> 16 & 0xfff, mask);
74 return hweight16(mask);
75
76 case HOST1X_OPCODE_IMM:
77 host1x_debug_output(o, "IMM(offset=%03x, data=%03x)\n",
78 val >> 16 & 0xfff, val & 0xffff);
79 return 0;
80
81 case HOST1X_OPCODE_RESTART:
82 host1x_debug_output(o, "RESTART(offset=%08x)\n", val << 4);
83 return 0;
84
85 case HOST1X_OPCODE_GATHER:
86 host1x_debug_output(o, "GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[",
87 val >> 16 & 0xfff, val >> 15 & 0x1,
88 val >> 14 & 0x1, val & 0x3fff);
89 return 1;
90
91 case HOST1X_OPCODE_EXTEND:
92 subop = val >> 24 & 0xf;
93 if (subop == HOST1X_OPCODE_EXTEND_ACQUIRE_MLOCK)
94 host1x_debug_output(o, "ACQUIRE_MLOCK(index=%d)\n",
95 val & 0xff);
96 else if (subop == HOST1X_OPCODE_EXTEND_RELEASE_MLOCK)
97 host1x_debug_output(o, "RELEASE_MLOCK(index=%d)\n",
98 val & 0xff);
99 else
100 host1x_debug_output(o, "EXTEND_UNKNOWN(%08x)\n", val);
101 return 0;
102
103 default:
104 return 0;
105 }
106}
107
108static void show_gather(struct output *o, phys_addr_t phys_addr,
109 unsigned int words, struct host1x_cdma *cdma,
110 phys_addr_t pin_addr, u32 *map_addr)
111{
112 /* Map dmaget cursor to corresponding mem handle */
113 u32 offset = phys_addr - pin_addr;
114 unsigned int data_count = 0, i;
115
116 /*
117 * Sometimes we're given different hardware address to the same
118 * page - in these cases the offset will get an invalid number and
119 * we just have to bail out.
120 */
121 if (offset > HOST1X_DEBUG_MAX_PAGE_OFFSET) {
122 host1x_debug_output(o, "[address mismatch]\n");
123 return;
124 }
125
126 for (i = 0; i < words; i++) {
127 u32 addr = phys_addr + i * 4;
128 u32 val = *(map_addr + offset / 4 + i);
129
130 if (!data_count) {
131 host1x_debug_output(o, "%08x: %08x:", addr, val);
132 data_count = show_channel_command(o, val);
133 } else {
134 host1x_debug_output(o, "%08x%s", val,
135 data_count > 0 ? ", " : "])\n");
136 data_count--;
137 }
138 }
139}
140
141static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
142{
143 struct host1x_job *job;
144
145 list_for_each_entry(job, &cdma->sync_queue, list) {
146 int i;
147 host1x_debug_output(o, "\n%p: JOB, syncpt_id=%d, syncpt_val=%d, first_get=%08x, timeout=%d num_slots=%d, num_handles=%d\n",
148 job,
149 (job->syncpts ? job->syncpts[0].id : 0),
150 (job->syncpts ? job->syncpts[0].end : 0),
151 job->first_get, job->timeout,
152 job->num_slots, job->num_unpins);
153
154 for (i = 0; i < job->num_gathers; i++) {
155 struct host1x_job_gather *g = &job->gathers[i];
156 u32 *mapped;
157
158 if (job->gather_copy_mapped)
159 mapped = (u32 *)job->gather_copy_mapped;
160 else
161 mapped = host1x_bo_mmap(g->bo);
162
163 if (!mapped) {
164 host1x_debug_output(o, "[could not mmap]\n");
165 continue;
166 }
167
168 host1x_debug_output(o, " GATHER at %pad+%#x, %d words\n",
169 &g->base, g->offset, g->words);
170
171 show_gather(o, g->base + g->offset, g->words, cdma,
172 g->base, mapped);
173
174 if (!job->gather_copy_mapped)
175 host1x_bo_munmap(g->bo, mapped);
176 }
177 }
178}
179
180static void host1x_debug_show_channel_cdma(struct host1x *host,
181 struct host1x_channel *ch,
182 struct output *o)
183{
184 struct host1x_cdma *cdma = &ch->cdma;
185 u32 val;
186
187 host1x_debug_output(o, "Host1x basic channel registers: \n");
188
189 val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT);
190 host1x_debug_output(o, "CMDFIFO_STAT_0: %08x\n", val);
191 val = host1x_ch_readl(ch, HOST1X_CHANNEL_RDATA);
192 host1x_debug_output(o, "CMDFIFO_RDATA_0: %08x\n", val);
193 val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_OFFSET);
194 host1x_debug_output(o, "CMDP_OFFSET_0: %08x\n", val);
195 val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_CLASS);
196 host1x_debug_output(o, "CMDP_CLASS_0: %08x\n", val);
197 val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_CHANNELSTAT);
198 host1x_debug_output(o, "CHANNELSTAT_0: %08x\n", val);
199
200 show_channel_gathers(o, cdma);
201 host1x_debug_output(o, "\n");
202}
203
204static void host1x_debug_show_channel_fifo(struct host1x *host,
205 struct host1x_channel *ch,
206 struct output *o)
207{
208 u32 val, rd_ptr, wr_ptr, start, end, temp;
209 unsigned int data_count = 0;
210
211 host1x_debug_output(o, "%d: fifo:\n", ch->id);
212
213 temp = host1x_sync_readl(host, HOST1X_THOST_COMMON_ICG_EN_OVERRIDE_0);
214 host1x_sync_writel(host, 0x1, HOST1X_THOST_COMMON_ICG_EN_OVERRIDE_0);
215
216 val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT);
217 host1x_debug_output(o, "FIFOSTAT %08x\n", val);
218 if (HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(val)) {
219 host1x_debug_output(o, "[empty]\n");
220 return;
221 }
222
223 host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
224 host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
225 HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id),
226 HOST1X_SYNC_CFPEEK_CTRL);
227
228 val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_PTRS);
229 rd_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(val);
230 wr_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(val);
231
232 val = host1x_sync_readl(host, HOST1X_SYNC_CF_SETUP(ch->id));
233 start = HOST1X_SYNC_CF_SETUP_BASE_V(val);
234 end = HOST1X_SYNC_CF_SETUP_LIMIT_V(val);
235
236 do {
237 host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
238 host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
239 HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id) |
240 HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(rd_ptr),
241 HOST1X_SYNC_CFPEEK_CTRL);
242 val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_READ);
243
244 if (!data_count) {
245 host1x_debug_output(o, "%08x:", val);
246 data_count = show_channel_command(o, val);
247 } else {
248 host1x_debug_output(o, "%08x%s", val,
249 data_count > 0 ? ", " : "])\n");
250 data_count--;
251 }
252
253 if (rd_ptr == end)
254 rd_ptr = start;
255 else
256 rd_ptr++;
257 } while (rd_ptr != wr_ptr);
258
259 if (data_count)
260 host1x_debug_output(o, ", ...])\n");
261 host1x_debug_output(o, "\n");
262
263 host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
264
265 host1x_sync_writel(host, temp, HOST1X_THOST_COMMON_ICG_EN_OVERRIDE_0);
266}
267
268static void host1x_debug_show_mlocks(struct host1x *host, struct output *o)
269{
270 int i;
271 unsigned int chid;
272 bool cpu, ch;
273
274 host1x_debug_output(o, "---- mlocks ----\n");
275 for (i = 0; i < host1x_syncpt_nb_mlocks(host); i++) {
276 host1x_hw_sync_get_mutex_owner(host, host->syncpt,
277 i, &cpu, &ch, &chid);
278 if (ch)
279 host1x_debug_output(o, "%d: locked by channel %d\n", i, chid);
280 }
281 host1x_debug_output(o, "\n");
282}
283
284static const struct host1x_debug_ops host1x_debug_t186_ops = {
285 .show_channel_cdma = host1x_debug_show_channel_cdma,
286 .show_channel_fifo = host1x_debug_show_channel_fifo,
287 .show_mlocks = host1x_debug_show_mlocks,
288};
diff --git a/drivers/gpu/host1x/hw/host1x05.c b/drivers/gpu/host1x/hw/host1x05.c
new file mode 100644
index 000000000..db64e7cfe
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x05.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17/* include hw specification */
18#include "host1x05.h"
19#include "host1x05_hardware.h"
20
21/* include code */
22#include "cdma_hw_t186.c"
23#include "channel_hw_t186.c"
24#include "debug_hw_t186.c"
25#include "intr_hw_t186.c"
26#include "syncpt_hw_t186.c"
27
28#include "dev.h"
29
30int host1x05_init(struct host1x *host)
31{
32 host->channel_op = &host1x_channel_t186_ops;
33 host->cdma_op = &host1x_cdma_t186_ops;
34 host->cdma_pb_op = &host1x_pushbuffer_t186_ops;
35 host->syncpt_op = &host1x_syncpt_t186_ops;
36 host->intr_op = &host1x_intr_t186_ops;
37 host->debug_op = &host1x_debug_t186_ops;
38
39 return 0;
40}
diff --git a/drivers/gpu/host1x/hw/host1x05.h b/drivers/gpu/host1x/hw/host1x05.h
new file mode 100644
index 000000000..e1b842146
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x05.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef HOST1X_HOST1X05_H
18#define HOST1X_HOST1X05_H
19
20struct host1x;
21
22int host1x05_init(struct host1x *host);
23
24#endif
diff --git a/drivers/gpu/host1x/hw/host1x05_hardware.h b/drivers/gpu/host1x/hw/host1x05_hardware.h
new file mode 100644
index 000000000..add00014e
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x05_hardware.h
@@ -0,0 +1,128 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __HOST1X_HOST1X05_HARDWARE_H
18#define __HOST1X_HOST1X05_HARDWARE_H
19
20#include <linux/types.h>
21#include <linux/bitops.h>
22
23#include "hw_host1x05_channel.h"
24#include "hw_host1x05_sync.h"
25#include "hw_host1x05_uclass.h"
26
27static inline u32 host1x_class_host_wait_syncpt(
28 unsigned indx, unsigned threshold)
29{
30 return host1x_uclass_wait_syncpt_indx_f(indx)
31 | host1x_uclass_wait_syncpt_thresh_f(threshold);
32}
33
34static inline u32 host1x_class_host_load_syncpt_base(
35 unsigned indx, unsigned threshold)
36{
37 return host1x_uclass_load_syncpt_base_base_indx_f(indx)
38 | host1x_uclass_load_syncpt_base_value_f(threshold);
39}
40
41static inline u32 host1x_class_host_wait_syncpt_base(
42 unsigned indx, unsigned base_indx, unsigned offset)
43{
44 return host1x_uclass_wait_syncpt_base_indx_f(indx)
45 | host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
46 | host1x_uclass_wait_syncpt_base_offset_f(offset);
47}
48
49static inline u32 host1x_class_host_incr_syncpt_base(
50 unsigned base_indx, unsigned offset)
51{
52 return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
53 | host1x_uclass_incr_syncpt_base_offset_f(offset);
54}
55
56static inline u32 host1x_class_host_incr_syncpt(
57 unsigned cond, unsigned indx)
58{
59 return host1x_uclass_incr_syncpt_cond_f(cond)
60 | host1x_uclass_incr_syncpt_indx_f(indx);
61}
62
63/* cdma opcodes */
64static inline u32 host1x_opcode_setclass(
65 unsigned class_id, unsigned offset, unsigned mask)
66{
67 return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
68}
69
70static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
71{
72 return (1 << 28) | (offset << 16) | count;
73}
74
75static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
76{
77 return (2 << 28) | (offset << 16) | count;
78}
79
80static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
81{
82 return (3 << 28) | (offset << 16) | mask;
83}
84
85static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
86{
87 return (4 << 28) | (offset << 16) | value;
88}
89
90static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
91{
92 return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
93 host1x_class_host_incr_syncpt(cond, indx));
94}
95
96static inline u32 host1x_opcode_restart(unsigned address)
97{
98 return (5 << 28) | (address >> 4);
99}
100
101static inline u32 host1x_opcode_gather(unsigned count)
102{
103 return (6 << 28) | count;
104}
105
106static inline u32 host1x_opcode_gather_nonincr(unsigned offset, unsigned count)
107{
108 return (6 << 28) | (offset << 16) | BIT(15) | count;
109}
110
111static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
112{
113 return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
114}
115
116static inline u32 host1x_opcode_acquire_mlock(unsigned id)
117{
118 return (14 << 28) | id;
119}
120
121static inline u32 host1x_opcode_release_mlock(unsigned id)
122{
123 return (14 << 28) | (1 << 24) | id;
124}
125
126#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
127
128#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x05_channel.h b/drivers/gpu/host1x/hw/hw_host1x05_channel.h
new file mode 100644
index 000000000..8c3499f91
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x05_channel.h
@@ -0,0 +1,169 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /*
19 * Function naming determines intended use:
20 *
21 * <x>_r(void) : Returns the offset for register <x>.
22 *
23 * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
24 *
25 * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
26 *
27 * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
28 * and masked to place it at field <y> of register <x>. This value
29 * can be |'d with others to produce a full register value for
30 * register <x>.
31 *
32 * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
33 * value can be ~'d and then &'d to clear the value of field <y> for
34 * register <x>.
35 *
36 * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
37 * to place it at field <y> of register <x>. This value can be |'d
38 * with others to produce a full register value for <x>.
39 *
40 * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
41 * <x> value 'r' after being shifted to place its LSB at bit 0.
42 * This value is suitable for direct comparison with other unshifted
43 * values appropriate for use in field <y> of register <x>.
44 *
45 * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
46 * field <y> of register <x>. This value is suitable for direct
47 * comparison with unshifted values appropriate for use in field <y>
48 * of register <x>.
49 */
50
51#ifndef HOST1X_HW_HOST1X05_CHANNEL_H
52#define HOST1X_HW_HOST1X05_CHANNEL_H
53
54static inline u32 host1x_channel_ch_aperture_start_r(void)
55{
56 return 0x10000;
57}
58#define HOST1X_CHANNEL_CH_APERTURE_START \
59 host1x_channel_ch_aperture_start_r()
60static inline u32 host1x_channel_ch_aperture_size_r(void)
61{
62 return 0x100;
63}
64#define HOST1X_CHANNEL_CH_APERTURE_SIZE \
65 host1x_channel_ch_aperture_size_r()
66static inline u32 host1x_channel_fifostat_r(void)
67{
68 return 0x24;
69}
70#define HOST1X_CHANNEL_FIFOSTAT \
71 host1x_channel_fifostat_r()
72static inline u32 host1x_channel_fifostat_cfempty_v(u32 r)
73{
74 return (r >> 13) & 0x1;
75}
76#define HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(r) \
77 host1x_channel_fifostat_cfempty_v(r)
78static inline u32 host1x_channel_rdata_r(void)
79{
80 return 0x28;
81}
82#define HOST1X_CHANNEL_RDATA \
83 host1x_channel_rdata_r()
84static inline u32 host1x_channel_cmdp_offset_r(void)
85{
86 return 0x30;
87}
88#define HOST1X_CHANNEL_CMDP_OFFSET \
89 host1x_channel_cmdp_offset_r()
90static inline u32 host1x_channel_cmdp_class_r(void)
91{
92 return 0x34;
93}
94#define HOST1X_CHANNEL_CMDP_CLASS \
95 host1x_channel_cmdp_class_r()
96static inline u32 host1x_channel_cmdp_channelstat_r(void)
97{
98 return 0x38;
99}
100#define HOST1X_CHANNEL_CMDP_CHANNELSTAT \
101 host1x_channel_cmdp_channelstat_r()
102static inline u32 host1x_channel_dmastart_r(void)
103{
104 return 0x0;
105}
106#define HOST1X_CHANNEL_DMASTART \
107 host1x_channel_dmastart_r()
108static inline u32 host1x_channel_dmaput_r(void)
109{
110 return 0x8;
111}
112#define HOST1X_CHANNEL_DMAPUT \
113 host1x_channel_dmaput_r()
114static inline u32 host1x_channel_dmaget_r(void)
115{
116 return 0x10;
117}
118#define HOST1X_CHANNEL_DMAGET \
119 host1x_channel_dmaget_r()
120static inline u32 host1x_channel_dmaend_r(void)
121{
122 return 0x18;
123}
124#define HOST1X_CHANNEL_DMAEND \
125 host1x_channel_dmaend_r()
126static inline u32 host1x_channel_dmactrl_r(void)
127{
128 return 0x20;
129}
130#define HOST1X_CHANNEL_DMACTRL \
131 host1x_channel_dmactrl_r()
132static inline u32 host1x_channel_dmactrl_dmastop(void)
133{
134 return 1 << 0;
135}
136#define HOST1X_CHANNEL_DMACTRL_DMASTOP \
137 host1x_channel_dmactrl_dmastop()
138static inline u32 host1x_channel_dmactrl_dmastop_v(u32 r)
139{
140 return (r >> 0) & 0x1;
141}
142#define HOST1X_CHANNEL_DMACTRL_DMASTOP_V(r) \
143 host1x_channel_dmactrl_dmastop_v(r)
144static inline u32 host1x_channel_dmactrl_dmagetrst(void)
145{
146 return 1 << 1;
147}
148#define HOST1X_CHANNEL_DMACTRL_DMAGETRST \
149 host1x_channel_dmactrl_dmagetrst()
150static inline u32 host1x_channel_dmactrl_dmainitget(void)
151{
152 return 1 << 2;
153}
154#define HOST1X_CHANNEL_DMACTRL_DMAINITGET \
155 host1x_channel_dmactrl_dmainitget()
156static inline u32 host1x_channel_smmu_streamid_r(void)
157{
158 return 0x84;
159}
160#define HOST1X_CHANNEL_SMMU_STREAMID \
161 host1x_channel_smmu_streamid_r()
162static inline u32 host1x_channel_filter_gbuffer_r(void)
163{
164 return 0x2020;
165}
166#define HOST1X_CHANNEL_FILTER_GBUFFER \
167 host1x_channel_filter_gbuffer_r()
168
169#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x05_sync.h b/drivers/gpu/host1x/hw/hw_host1x05_sync.h
new file mode 100644
index 000000000..55fe98859
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x05_sync.h
@@ -0,0 +1,321 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /*
19 * Function naming determines intended use:
20 *
21 * <x>_r(void) : Returns the offset for register <x>.
22 *
23 * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
24 *
25 * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
26 *
27 * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
28 * and masked to place it at field <y> of register <x>. This value
29 * can be |'d with others to produce a full register value for
30 * register <x>.
31 *
32 * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
33 * value can be ~'d and then &'d to clear the value of field <y> for
34 * register <x>.
35 *
36 * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
37 * to place it at field <y> of register <x>. This value can be |'d
38 * with others to produce a full register value for <x>.
39 *
40 * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
41 * <x> value 'r' after being shifted to place its LSB at bit 0.
42 * This value is suitable for direct comparison with other unshifted
43 * values appropriate for use in field <y> of register <x>.
44 *
45 * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
46 * field <y> of register <x>. This value is suitable for direct
47 * comparison with unshifted values appropriate for use in field <y>
48 * of register <x>.
49 */
50
51#ifndef HOST1X_HW_HOST1X05_SYNC_H
52#define HOST1X_HW_HOST1X05_SYNC_H
53
54#define REGISTER_STRIDE 4
55
56static inline u32 host1x_sync_intstatus_r(void)
57{
58 return 0x1c;
59}
60#define HOST1X_SYNC_INTSTATUS \
61 host1x_sync_intstatus_r()
62static inline u32 host1x_sync_intmask_r(void)
63{
64 return 0x30;
65}
66#define HOST1X_SYNC_INTMASK \
67 host1x_sync_intmask_r()
68static inline u32 host1x_sync_intc0mask_r(void)
69{
70 return 0x4;
71}
72#define HOST1X_SYNC_INTC0MASK \
73 host1x_sync_intc0mask_r()
74static inline u32 host1x_sync_intgmask_r(void)
75{
76 return 0x44;
77}
78#define HOST1X_SYNC_INTGMASK \
79 host1x_sync_intgmask_r()
80static inline u32 host1x_sync_syncpt_intgmask_r(void)
81{
82 return 0x50;
83}
84#define HOST1X_SYNC_SYNCPT_INTGMASK \
85 host1x_sync_syncpt_intgmask_r()
86static inline u32 host1x_sync_intstatus_ip_read_int_v(u32 r)
87{
88 return (r >> 0) & 0x1;
89}
90#define HOST1X_SYNC_INTSTATUS_IP_READ_INT_V(r) \
91 host1x_sync_intstatus_ip_read_int_v(r)
92static inline u32 host1x_sync_intstatus_ip_write_int_v(u32 r)
93{
94 return (r >> 1) & 0x1;
95}
96#define HOST1X_SYNC_INTSTATUS_IP_WRITE_INT_V(r) \
97 host1x_sync_intstatus_ip_write_int_v(r)
98static inline u32 host1x_sync_intstatus_illegal_pb_access_v(u32 r)
99{
100 return (r >> 28) & 0x1;
101}
102#define HOST1X_SYNC_INTSTATUS_ILLEGAL_PB_ACCESS_V(r) \
103 host1x_sync_intstatus_illegal_pb_access_v(r)
104static inline u32 host1x_sync_illegal_syncpt_access_frm_pb_r(void)
105{
106 return 0x2270;
107}
108#define HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_PB \
109 host1x_sync_illegal_syncpt_access_frm_pb_r()
110static inline u32 host1x_sync_illegal_syncpt_access_frm_pb_syncpt_v(u32 r)
111{
112 return (r >> 16) & 0x3ff;
113}
114#define HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_PB_SYNCPT_V(r) \
115 host1x_sync_illegal_syncpt_access_frm_pb_syncpt_v(r)
116static inline u32 host1x_sync_illegal_syncpt_access_frm_pb_ch_v(u32 r)
117{
118 return (r >> 10) & 0x3f;
119}
120#define HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_PB_CH_V(r) \
121 host1x_sync_illegal_syncpt_access_frm_pb_ch_v(r)
122static inline u32 host1x_sync_intstatus_illegal_client_access_v(u32 r)
123{
124 return (r >> 30) & 0x1;
125}
126#define HOST1X_SYNC_INTSTATUS_ILLEGAL_CLIENT_ACCESS_V(r) \
127 host1x_sync_intstatus_illegal_client_access_v(r)
128static inline u32 host1x_sync_illegal_syncpt_access_frm_client_r(void)
129{
130 return 0x2268;
131}
132#define HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_CLIENT \
133 host1x_sync_illegal_syncpt_access_frm_client_r()
134static inline u32 host1x_sync_illegal_syncpt_access_frm_client_syncpt_v(u32 r)
135{
136 return (r >> 16) & 0x3ff;
137}
138#define HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_CLIENT_SYNCPT_V(r) \
139 host1x_sync_illegal_syncpt_access_frm_client_syncpt_v(r)
140static inline u32 host1x_sync_illegal_syncpt_access_frm_client_ch_v(u32 r)
141{
142 return (r >> 10) & 0x3f;
143}
144#define HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_CLIENT_CH_V(r) \
145 host1x_sync_illegal_syncpt_access_frm_client_ch_v(r)
146static inline u32 host1x_sync_syncpt_r(unsigned int id)
147{
148 return 0x18080 + id * REGISTER_STRIDE;
149}
150#define HOST1X_SYNC_SYNCPT(id) \
151 host1x_sync_syncpt_r(id)
152static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_r(unsigned int id)
153{
154 return 0x16464 + id * REGISTER_STRIDE;
155}
156#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id) \
157 host1x_sync_syncpt_thresh_cpu0_int_status_r(id)
158static inline u32 host1x_sync_syncpt_thresh_int_disable_r(unsigned int id)
159{
160 return 0x16590 + id * REGISTER_STRIDE;
161}
162#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id) \
163 host1x_sync_syncpt_thresh_int_disable_r(id)
164static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_r(unsigned int id)
165{
166 return 0x1652c + id * REGISTER_STRIDE;
167}
168#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id) \
169 host1x_sync_syncpt_thresh_int_enable_cpu0_r(id)
170static inline u32 host1x_sync_cf_setup_r(unsigned int channel)
171{
172 return 0x2588 + channel * REGISTER_STRIDE;
173}
174#define HOST1X_SYNC_CF_SETUP(channel) \
175 host1x_sync_cf_setup_r(channel)
176static inline u32 host1x_sync_cf_setup_base_v(u32 r)
177{
178 return (r >> 0) & 0xfff;
179}
180#define HOST1X_SYNC_CF_SETUP_BASE_V(r) \
181 host1x_sync_cf_setup_base_v(r)
182static inline u32 host1x_sync_cf_setup_limit_v(u32 r)
183{
184 return (r >> 16) & 0xfff;
185}
186#define HOST1X_SYNC_CF_SETUP_LIMIT_V(r) \
187 host1x_sync_cf_setup_limit_v(r)
188static inline u32 host1x_sync_cmdproc_stop_r(void)
189{
190 return 0x48;
191}
192#define HOST1X_SYNC_CMDPROC_STOP \
193 host1x_sync_cmdproc_stop_r()
194static inline u32 host1x_sync_ch_teardown_r(void)
195{
196 return 0x4c;
197}
198#define HOST1X_SYNC_CH_TEARDOWN \
199 host1x_sync_ch_teardown_r()
200static inline u32 host1x_sync_usec_clk_r(void)
201{
202 return 0x2244;
203}
204#define HOST1X_SYNC_USEC_CLK \
205 host1x_sync_usec_clk_r()
206static inline u32 host1x_sync_ctxsw_timeout_cfg_r(void)
207{
208 return 0x2248;
209}
210#define HOST1X_SYNC_CTXSW_TIMEOUT_CFG \
211 host1x_sync_ctxsw_timeout_cfg_r()
212static inline u32 host1x_sync_ip_busy_timeout_r(void)
213{
214 return 0x2250;
215}
216#define HOST1X_SYNC_IP_BUSY_TIMEOUT \
217 host1x_sync_ip_busy_timeout_r()
218static inline u32 host1x_sync_ip_read_timeout_addr_r(void)
219{
220 return 0x2254;
221}
222#define HOST1X_SYNC_IP_READ_TIMEOUT_ADDR \
223 host1x_sync_ip_read_timeout_addr_r()
224static inline u32 host1x_sync_ip_write_timeout_addr_r(void)
225{
226 return 0x225c;
227}
228#define HOST1X_SYNC_IP_WRITE_TIMEOUT_ADDR \
229 host1x_sync_ip_write_timeout_addr_r()
230static inline u32 host1x_sync_syncpt_int_thresh_r(unsigned int id)
231{
232 return 0x18a00 + id * REGISTER_STRIDE;
233}
234#define HOST1X_SYNC_SYNCPT_INT_THRESH(id) \
235 host1x_sync_syncpt_int_thresh_r(id)
236static inline u32 host1x_sync_syncpt_base_r(unsigned int id)
237{
238 return 0x18000 + id * REGISTER_STRIDE;
239}
240#define HOST1X_SYNC_SYNCPT_BASE(id) \
241 host1x_sync_syncpt_base_r(id)
242static inline u32 host1x_sync_syncpt_cpu_incr_r(unsigned int id)
243{
244 return 0x16400 + id * REGISTER_STRIDE;
245}
246#define HOST1X_SYNC_SYNCPT_CPU_INCR(id) \
247 host1x_sync_syncpt_cpu_incr_r(id)
248static inline u32 host1x_sync_cfpeek_ctrl_r(void)
249{
250 return 0x233c;
251}
252#define HOST1X_SYNC_CFPEEK_CTRL \
253 host1x_sync_cfpeek_ctrl_r()
254static inline u32 host1x_sync_cfpeek_ctrl_addr_f(u32 v)
255{
256 return (v & 0xfff) << 0;
257}
258#define HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(v) \
259 host1x_sync_cfpeek_ctrl_addr_f(v)
260static inline u32 host1x_sync_cfpeek_ctrl_channr_f(u32 v)
261{
262 return (v & 0x3f) << 16;
263}
264#define HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(v) \
265 host1x_sync_cfpeek_ctrl_channr_f(v)
266static inline u32 host1x_sync_cfpeek_ctrl_ena_f(u32 v)
267{
268 return (v & 0x1) << 31;
269}
270#define HOST1X_SYNC_CFPEEK_CTRL_ENA_F(v) \
271 host1x_sync_cfpeek_ctrl_ena_f(v)
272static inline u32 host1x_sync_cfpeek_read_r(void)
273{
274 return 0x2340;
275}
276#define HOST1X_SYNC_CFPEEK_READ \
277 host1x_sync_cfpeek_read_r()
278static inline u32 host1x_sync_cfpeek_ptrs_r(void)
279{
280 return 0x2344;
281}
282#define HOST1X_SYNC_CFPEEK_PTRS \
283 host1x_sync_cfpeek_ptrs_r()
284static inline u32 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(u32 r)
285{
286 return (r >> 0) & 0xfff;
287}
288#define HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(r) \
289 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(r)
290static inline u32 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(u32 r)
291{
292 return (r >> 16) & 0xfff;
293}
294#define HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(r) \
295 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(r)
296static inline u32 host1x_sync_common_mlock_r(unsigned long id)
297{
298 return 0x2030 + id * REGISTER_STRIDE;
299}
300#define HOST1X_SYNC_COMMON_MLOCK \
301 host1x_sync_common_mlock_r()
302static inline u32 host1x_sync_common_mlock_ch_v(u32 r)
303{
304 return (r >> 2) & 0x3f;
305}
306#define HOST1X_SYNC_COMMON_MLOCK_CH_V(r) \
307 host1x_sync_common_mlock_ch_v(r)
308static inline u32 host1x_sync_common_mlock_locked_v(u32 r)
309{
310 return (r >> 0) & 0x1;
311}
312#define HOST1X_SYNC_COMMON_MLOCK_LOCKED_V(r) \
313 host1x_sync_common_mlock_locked_v(r)
314static inline u32 host1x_thost_common_icg_en_override_0_r(void)
315{
316 return 0x2aa8;
317}
318#define HOST1X_THOST_COMMON_ICG_EN_OVERRIDE_0 \
319 host1x_thost_common_icg_en_override_0_r()
320
321#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x05_uclass.h b/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
new file mode 100644
index 000000000..01145f610
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /*
19 * Function naming determines intended use:
20 *
21 * <x>_r(void) : Returns the offset for register <x>.
22 *
23 * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
24 *
25 * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
26 *
27 * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
28 * and masked to place it at field <y> of register <x>. This value
29 * can be |'d with others to produce a full register value for
30 * register <x>.
31 *
32 * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
33 * value can be ~'d and then &'d to clear the value of field <y> for
34 * register <x>.
35 *
36 * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
37 * to place it at field <y> of register <x>. This value can be |'d
38 * with others to produce a full register value for <x>.
39 *
40 * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
41 * <x> value 'r' after being shifted to place its LSB at bit 0.
42 * This value is suitable for direct comparison with other unshifted
43 * values appropriate for use in field <y> of register <x>.
44 *
45 * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
46 * field <y> of register <x>. This value is suitable for direct
47 * comparison with unshifted values appropriate for use in field <y>
48 * of register <x>.
49 */
50
51#ifndef HOST1X_HW_HOST1X05_UCLASS_H
52#define HOST1X_HW_HOST1X05_UCLASS_H
53
54static inline u32 host1x_uclass_incr_syncpt_r(void)
55{
56 return 0x0;
57}
58#define HOST1X_UCLASS_INCR_SYNCPT \
59 host1x_uclass_incr_syncpt_r()
60static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
61{
62 return (v & 0xff) << 10;
63}
64#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \
65 host1x_uclass_incr_syncpt_cond_f(v)
66static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
67{
68 return (v & 0x3ff) << 0;
69}
70#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \
71 host1x_uclass_incr_syncpt_indx_f(v)
72static inline u32 host1x_uclass_load_syncpt_payload_32_r(void)
73{
74 return 0x4e;
75}
76#define HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32 \
77 host1x_uclass_load_syncpt_payload_32_r()
78static inline u32 host1x_uclass_wait_syncpt_32_r(void)
79{
80 return 0x50;
81}
82#define HOST1X_UCLASS_WAIT_SYNCPT_32 \
83 host1x_uclass_wait_syncpt_32_r()
84static inline u32 host1x_uclass_wait_syncpt_r(void)
85{
86 return 0x8;
87}
88#define HOST1X_UCLASS_WAIT_SYNCPT \
89 host1x_uclass_wait_syncpt_r()
90static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v)
91{
92 return (v & 0xff) << 24;
93}
94#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \
95 host1x_uclass_wait_syncpt_indx_f(v)
96static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v)
97{
98 return (v & 0xffffff) << 0;
99}
100#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \
101 host1x_uclass_wait_syncpt_thresh_f(v)
102static inline u32 host1x_uclass_wait_syncpt_base_r(void)
103{
104 return 0x9;
105}
106#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \
107 host1x_uclass_wait_syncpt_base_r()
108static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v)
109{
110 return (v & 0x3ff) << 22;
111}
112#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \
113 host1x_uclass_wait_syncpt_base_indx_f(v)
114static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v)
115{
116 return (v & 0x3f) << 16;
117}
118#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \
119 host1x_uclass_wait_syncpt_base_base_indx_f(v)
120static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
121{
122 return (v & 0xffff) << 0;
123}
124#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
125 host1x_uclass_wait_syncpt_base_offset_f(v)
126static inline u32 host1x_uclass_load_syncpt_base_r(void)
127{
128 return 0xb;
129}
130#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
131 host1x_uclass_load_syncpt_base_r()
132static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
133{
134 return (v & 0xff) << 24;
135}
136#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \
137 host1x_uclass_load_syncpt_base_base_indx_f(v)
138static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v)
139{
140 return (v & 0xffffff) << 0;
141}
142#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \
143 host1x_uclass_load_syncpt_base_value_f(v)
144static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v)
145{
146 return (v & 0xff) << 24;
147}
148#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \
149 host1x_uclass_incr_syncpt_base_base_indx_f(v)
150static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v)
151{
152 return (v & 0xffffff) << 0;
153}
154#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \
155 host1x_uclass_incr_syncpt_base_offset_f(v)
156
157#endif
diff --git a/drivers/gpu/host1x/hw/intr_hw_t186.c b/drivers/gpu/host1x/hw/intr_hw_t186.c
new file mode 100644
index 000000000..48bd1150f
--- /dev/null
+++ b/drivers/gpu/host1x/hw/intr_hw_t186.c
@@ -0,0 +1,247 @@
1/*
2 * Tegra host1x Interrupt Management
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2016 NVIDIA Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22#include <linux/io.h>
23
24#include "intr.h"
25#include "dev.h"
26
27
28static inline u32 bit_mask(u32 nr)
29{
30 return 1UL << (nr % 32);
31}
32static inline u32 bit_word(u32 nr)
33{
34 return nr / 32;
35}
36
37/*
38 * Sync point threshold interrupt service function
39 * Handles sync point threshold triggers, in interrupt context
40 */
41static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt)
42{
43 unsigned int id = syncpt->id;
44 struct host1x *host = syncpt->host;
45
46 host1x_sync_writel(host, bit_mask(id),
47 HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(bit_word(id)));
48 host1x_sync_writel(host, bit_mask(id),
49 HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(bit_word(id)));
50
51 queue_work(host->intr_wq, &syncpt->intr.work);
52}
53
54static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
55{
56 struct host1x *host = dev_id;
57 unsigned long reg;
58 int i, set_bit;
59
60 for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {
61 reg = host1x_sync_readl(host,
62 HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
63 for_each_set_bit(set_bit, &reg, 32) {
64 struct host1x_syncpt *syncpt;
65 int id = i * 32 + set_bit;
66
67 if (unlikely(id < 0 || id >= host->info->nb_pts)) {
68 dev_err(host->dev,
69 "%s(): unexptected syncpt id %d\n",
70 __func__, id);
71 goto out;
72 }
73 syncpt = host->syncpt + id;
74 host1x_intr_syncpt_handle(syncpt);
75 }
76 }
77out:
78 return IRQ_HANDLED;
79}
80
81static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host)
82{
83 u32 i;
84
85 for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) {
86 host1x_sync_writel(host, 0xffffffffu,
87 HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i));
88 host1x_sync_writel(host, 0xffffffffu,
89 HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
90 }
91}
92
93static int _host1x_intr_init_host_sync(struct host1x *host, u32 cpm,
94 void (*syncpt_thresh_work)(struct work_struct *))
95{
96 int i, err;
97
98 host1x_hw_intr_disable_all_syncpt_intrs(host);
99
100 for (i = 0; i < host->info->nb_pts; i++)
101 INIT_WORK(&host->syncpt[i].intr.work, syncpt_thresh_work);
102
103 err = devm_request_irq(host->dev, host->intr_syncpt_irq,
104 syncpt_thresh_isr, IRQF_SHARED,
105 "host1x_syncpt", host);
106 if (IS_ERR_VALUE(err)) {
107 WARN_ON(1);
108 return err;
109 }
110
111 /* disable the ip_busy_timeout. this prevents write drops */
112 host1x_sync_writel(host, 0, HOST1X_SYNC_IP_BUSY_TIMEOUT);
113
114 /*
115 * increase the auto-ack timout to the maximum value. 2d will hang
116 * otherwise on Tegra2.
117 */
118 host1x_sync_writel(host, 0xff, HOST1X_SYNC_CTXSW_TIMEOUT_CFG);
119
120 /* update host clocks per usec */
121 host1x_sync_writel(host, cpm, HOST1X_SYNC_USEC_CLK);
122
123 return 0;
124}
125
126static void _host1x_intr_set_syncpt_threshold(struct host1x *host,
127 u32 id, u32 thresh)
128{
129 host1x_sync_writel(host, thresh, HOST1X_SYNC_SYNCPT_INT_THRESH(id));
130}
131
132static void _host1x_intr_enable_syncpt_intr(struct host1x *host, u32 id)
133{
134 host1x_sync_writel(host, bit_mask(id),
135 HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(bit_word(id)));
136}
137
138static void _host1x_intr_disable_syncpt_intr(struct host1x *host, u32 id)
139{
140 host1x_sync_writel(host, bit_mask(id),
141 HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(bit_word(id)));
142 host1x_sync_writel(host, bit_mask(id),
143 HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(bit_word(id)));
144}
145
146static int _host1x_free_syncpt_irq(struct host1x *host)
147{
148 devm_free_irq(host->dev, host->intr_syncpt_irq, host);
149 flush_workqueue(host->intr_wq);
150 return 0;
151}
152
153/**
154 * Host general interrupt service function
155 * Handles read / write failures
156 */
157static irqreturn_t general_isr(int irq, void *dev_id)
158{
159 struct host1x *host = dev_id;
160 u32 intstatus, addr;
161
162 /* Handle host1x interrupt in ISR */
163 intstatus = host1x_sync_readl(host, HOST1X_SYNC_INTSTATUS);
164
165 if (HOST1X_SYNC_INTSTATUS_IP_READ_INT_V(intstatus)) {
166 addr = host1x_sync_readl(host,
167 HOST1X_SYNC_IP_READ_TIMEOUT_ADDR);
168 pr_err("Host read timeout at address %x\n", addr);
169 }
170
171 if (HOST1X_SYNC_INTSTATUS_IP_WRITE_INT_V(intstatus)) {
172 addr = host1x_sync_readl(host,
173 HOST1X_SYNC_IP_WRITE_TIMEOUT_ADDR);
174 pr_err("Host write timeout at address %x\n", addr);
175 }
176
177 if (HOST1X_SYNC_INTSTATUS_ILLEGAL_PB_ACCESS_V(intstatus)) {
178 u32 stat = host1x_sync_readl(host, HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_PB);
179 u32 ch = HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_PB_CH_V(stat);
180 u32 id = HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_PB_SYNCPT_V(stat);
181 pr_err("Host illegal syncpoint pb access (ch=%u, id=%u)\n", ch, id);
182 }
183
184 if (HOST1X_SYNC_INTSTATUS_ILLEGAL_CLIENT_ACCESS_V(intstatus)) {
185 u32 stat = host1x_sync_readl(host, HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_CLIENT);
186 u32 ch = HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_CLIENT_CH_V(stat);
187 u32 id = HOST1X_SYNC_ILLEGAL_SYNCPT_ACCESS_FRM_CLIENT_SYNCPT_V(stat);
188 pr_err("Host illegal syncpoint client access (ch=%u, id=%u)\n", ch, id);
189 }
190
191 host1x_sync_writel(host, intstatus, HOST1X_SYNC_INTSTATUS);
192
193 return IRQ_HANDLED;
194}
195
196static int _host1x_intr_request_host_general_irq(struct host1x *host)
197{
198 int err;
199
200 /* master disable for general (not syncpt) host interrupts */
201 host1x_sync_writel(host, 0, HOST1X_SYNC_INTC0MASK);
202 host1x_sync_writel(host, 0, HOST1X_SYNC_INTGMASK);
203 host1x_sync_writel(host, 0, HOST1X_SYNC_INTMASK);
204
205 err = devm_request_irq(host->dev, host->intr_general_irq,
206 general_isr, 0,
207 "host1x_general", host);
208 if (IS_ERR_VALUE(err)) {
209 WARN_ON(1);
210 return err;
211 }
212
213 /* enable host module interrupt to CPU0 */
214 host1x_sync_writel(host, BIT(0), HOST1X_SYNC_INTC0MASK);
215 host1x_sync_writel(host, BIT(0), HOST1X_SYNC_INTGMASK);
216 host1x_sync_writel(host, 0xff << 8, HOST1X_SYNC_SYNCPT_INTGMASK);
217
218 /* master enable for general (not syncpt) host interrupts
219 * (AXIREAD, AXIWRITE, Syncpoint protection */
220 host1x_sync_writel(host, BIT(0) | BIT(1) | BIT(28) | BIT(30),
221 HOST1X_SYNC_INTMASK);
222
223 return err;
224}
225
226static void _host1x_intr_free_host_general_irq(struct host1x *host)
227{
228 /* master disable for general (not syncpt) host interrupts */
229 host1x_sync_writel(host, 0, HOST1X_SYNC_INTMASK);
230 host1x_sync_writel(host, 0, HOST1X_SYNC_SYNCPT_INTGMASK);
231
232 devm_free_irq(host->dev, host->intr_general_irq, host);
233}
234
235static const struct host1x_intr_ops host1x_intr_t186_ops = {
236 /* Syncpt interrupts */
237 .init_host_sync = _host1x_intr_init_host_sync,
238 .set_syncpt_threshold = _host1x_intr_set_syncpt_threshold,
239 .enable_syncpt_intr = _host1x_intr_enable_syncpt_intr,
240 .disable_syncpt_intr = _host1x_intr_disable_syncpt_intr,
241 .disable_all_syncpt_intrs = _host1x_intr_disable_all_syncpt_intrs,
242 .free_syncpt_irq = _host1x_free_syncpt_irq,
243
244 /* Host general interrupts */
245 .request_host_general_irq = _host1x_intr_request_host_general_irq,
246 .free_host_general_irq = _host1x_intr_free_host_general_irq,
247};
diff --git a/drivers/gpu/host1x/hw/syncpt_hw_t186.c b/drivers/gpu/host1x/hw/syncpt_hw_t186.c
new file mode 100644
index 000000000..9b196854a
--- /dev/null
+++ b/drivers/gpu/host1x/hw/syncpt_hw_t186.c
@@ -0,0 +1,126 @@
1/*
2 * Tegra host1x Syncpoints
3 *
4 * Copyright (c) 2016, NVIDIA Corporation.
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 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/io.h>
20
21#include "dev.h"
22#include "syncpt.h"
23
24/*
25 * Write the current syncpoint value back to hw.
26 */
27static void syncpt_restore(struct host1x_syncpt *sp)
28{
29 struct host1x *host = sp->host;
30 int min = host1x_syncpt_read_min(sp);
31 host1x_sync_writel(host, min, HOST1X_SYNC_SYNCPT(sp->id));
32}
33
34/*
35 * Write the current waitbase value back to hw.
36 */
37static void syncpt_restore_wait_base(struct host1x_syncpt *sp)
38{
39 struct host1x *host = sp->host;
40 host1x_sync_writel(host, sp->base_val,
41 HOST1X_SYNC_SYNCPT_BASE(sp->id));
42}
43
44/*
45 * Read waitbase value from hw.
46 */
47static void syncpt_read_wait_base(struct host1x_syncpt *sp)
48{
49 struct host1x *host = sp->host;
50 sp->base_val =
51 host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(sp->id));
52}
53
54/*
55 * Updates the last value read from hardware.
56 */
57static u32 syncpt_load(struct host1x_syncpt *sp)
58{
59 struct host1x *host = sp->host;
60 u32 old, live;
61
62 /* Loop in case there's a race writing to min_val */
63 do {
64 old = host1x_syncpt_read_min(sp);
65 live = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT(sp->id));
66 } while ((u32)atomic_cmpxchg(&sp->min_val, old, live) != old);
67
68 if (!host1x_syncpt_check_max(sp, live))
69 dev_err(host->dev, "%s failed: id=%u, min=%d, max=%d\n",
70 __func__, sp->id, host1x_syncpt_read_min(sp),
71 host1x_syncpt_read_max(sp));
72
73 return live;
74}
75
76/*
77 * Write a cpu syncpoint increment to the hardware, without touching
78 * the cache.
79 */
80static int syncpt_cpu_incr(struct host1x_syncpt *sp)
81{
82 struct host1x *host = sp->host;
83 u32 reg_offset = sp->id / 32;
84
85 if (!host1x_syncpt_client_managed(sp) &&
86 host1x_syncpt_idle(sp))
87 return -EINVAL;
88 host1x_sync_writel(host, BIT_MASK(sp->id),
89 HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
90 wmb();
91
92 return 0;
93}
94
95/* remove a wait pointed to by patch_addr */
96static int syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
97{
98 u32 override = host1x_class_host_wait_syncpt(
99 HOST1X_SYNCPT_RESERVED, 0);
100
101 *((u32 *)patch_addr) = override;
102 return 0;
103}
104
105static void syncpt_get_mutex_owner(struct host1x_syncpt *sp,
106 unsigned int mutex_id, bool *cpu, bool *ch,
107 unsigned int *chid)
108{
109 struct host1x *host = sp->host;
110 u32 owner;
111
112 owner = host1x_sync_readl(host, host1x_sync_common_mlock_r(mutex_id));
113 *chid = HOST1X_SYNC_COMMON_MLOCK_CH_V(owner);
114 *ch = HOST1X_SYNC_COMMON_MLOCK_LOCKED_V(owner);
115 *cpu = false;
116}
117
118static const struct host1x_syncpt_ops host1x_syncpt_t186_ops = {
119 .restore = syncpt_restore,
120 .restore_wait_base = syncpt_restore_wait_base,
121 .load_wait_base = syncpt_read_wait_base,
122 .load = syncpt_load,
123 .cpu_incr = syncpt_cpu_incr,
124 .patch_wait = syncpt_patch_wait,
125 .get_mutex_owner = syncpt_get_mutex_owner,
126};