xref: /linux/drivers/gpu/drm/nouveau/nvif/chanc36f.c (revision b08494a8f7416e5f09907318c5460ad6f6e2a548)
1 /* SPDX-License-Identifier: MIT
2  *
3  * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
4  */
5 #include <nvif/chan.h>
6 #include <nvif/user.h>
7 
8 #include <nvif/push906f.h>
9 #include <nvhw/class/clc36f.h>
10 
11 static void
12 nvif_chanc36f_gpfifo_kick(struct nvif_chan *chan)
13 {
14 	struct nvif_user *usermode = chan->usermode;
15 
16 	nvif_wr32(&chan->userd, 0x8c, chan->gpfifo.cur);
17 
18 	wmb(); /* ensure CPU writes are flushed to BAR1 */
19 	nvif_rd32(&chan->userd, 0); /* ensure BAR1 writes are flushed to vidmem */
20 
21 	usermode->func->doorbell(usermode, chan->doorbell_token);
22 }
23 
24 #define NVIF_CHANC36F_SEM_RELEASE_SIZE 6
25 
26 static int
27 nvif_chanc36f_sem_release(struct nvif_chan *chan, u64 addr, u32 data)
28 {
29 	struct nvif_push *push = &chan->push;
30 	int ret;
31 
32 	ret = PUSH_WAIT(push, NVIF_CHANC36F_SEM_RELEASE_SIZE);
33 	if (ret)
34 		return ret;
35 
36 	PUSH_MTHD(push, NVC36F, SEM_ADDR_LO, lower_32_bits(addr),
37 
38 				SEM_ADDR_HI, upper_32_bits(addr),
39 
40 				SEM_PAYLOAD_LO, data);
41 
42 	PUSH_MTHD(push, NVC36F, SEM_EXECUTE,
43 		  NVDEF(NVC36F, SEM_EXECUTE, OPERATION, RELEASE) |
44 		  NVDEF(NVC36F, SEM_EXECUTE, RELEASE_WFI, DIS) |
45 		  NVDEF(NVC36F, SEM_EXECUTE, PAYLOAD_SIZE, 32BIT) |
46 		  NVDEF(NVC36F, SEM_EXECUTE, RELEASE_TIMESTAMP, DIS));
47 
48 	return 0;
49 }
50 
51 static const struct nvif_chan_func
52 nvif_chanc36f = {
53 	.push.read_get = nvif_chan906f_read_get,
54 	.gpfifo.read_get = nvif_chan906f_gpfifo_read_get,
55 	.gpfifo.push = nvif_chan506f_gpfifo_push,
56 	.gpfifo.kick = nvif_chanc36f_gpfifo_kick,
57 	.gpfifo.post = nvif_chan906f_gpfifo_post,
58 	.gpfifo.post_size = NVIF_CHANC36F_SEM_RELEASE_SIZE,
59 	.sem.release = nvif_chanc36f_sem_release,
60 };
61 
62 int
63 nvif_chanc36f_ctor(struct nvif_chan *chan, void *userd, void *gpfifo, u32 gpfifo_size,
64 		   void *push, u64 push_addr, u32 push_size, void *sema, u64 sema_addr,
65 		   struct nvif_user *usermode, u32 doorbell_token)
66 {
67 	int ret;
68 
69 	ret = nvif_chan906f_ctor_(&nvif_chanc36f, userd, gpfifo, gpfifo_size,
70 				  push, push_addr, push_size, sema, sema_addr, chan);
71 	if (ret)
72 		return ret;
73 
74 	chan->usermode = usermode;
75 	chan->doorbell_token = doorbell_token;
76 	return 0;
77 }
78