1 // SPDX-License-Identifier: MIT
2 #ifndef __NVKM_PMU_MEMX_H__
3 #define __NVKM_PMU_MEMX_H__
18 memx_out(struct nvkm_memx
*memx
)
20 struct nvkm_device
*device
= memx
->pmu
->subdev
.device
;
24 nvkm_wr32(device
, 0x10a1c4, (memx
->c
.size
<< 16) | memx
->c
.mthd
);
25 for (i
= 0; i
< memx
->c
.size
; i
++)
26 nvkm_wr32(device
, 0x10a1c4, memx
->c
.data
[i
]);
33 memx_cmd(struct nvkm_memx
*memx
, u32 mthd
, u32 size
, u32 data
[])
35 if ((memx
->c
.size
+ size
>= ARRAY_SIZE(memx
->c
.data
)) ||
36 (memx
->c
.mthd
&& memx
->c
.mthd
!= mthd
))
38 memcpy(&memx
->c
.data
[memx
->c
.size
], data
, size
* sizeof(data
[0]));
44 nvkm_memx_init(struct nvkm_pmu
*pmu
, struct nvkm_memx
**pmemx
)
46 struct nvkm_device
*device
= pmu
->subdev
.device
;
47 struct nvkm_memx
*memx
;
51 ret
= nvkm_pmu_send(pmu
, reply
, PROC_MEMX
, MEMX_MSG_INFO
,
56 memx
= *pmemx
= kzalloc(sizeof(*memx
), GFP_KERNEL
);
60 memx
->base
= reply
[0];
61 memx
->size
= reply
[1];
63 /* acquire data segment access */
65 nvkm_wr32(device
, 0x10a580, 0x00000003);
66 } while (nvkm_rd32(device
, 0x10a580) != 0x00000003);
67 nvkm_wr32(device
, 0x10a1c0, 0x01000000 | memx
->base
);
72 nvkm_memx_fini(struct nvkm_memx
**pmemx
, bool exec
)
74 struct nvkm_memx
*memx
= *pmemx
;
75 struct nvkm_pmu
*pmu
= memx
->pmu
;
76 struct nvkm_subdev
*subdev
= &pmu
->subdev
;
77 struct nvkm_device
*device
= subdev
->device
;
80 /* flush the cache... */
83 /* release data segment access */
84 finish
= nvkm_rd32(device
, 0x10a1c0) & 0x00ffffff;
85 nvkm_wr32(device
, 0x10a580, 0x00000000);
87 /* call MEMX process to execute the script, and wait for reply */
89 nvkm_pmu_send(pmu
, reply
, PROC_MEMX
, MEMX_MSG_EXEC
,
91 nvkm_debug(subdev
, "Exec took %uns, PMU_IN %08x\n",
100 nvkm_memx_wr32(struct nvkm_memx
*memx
, u32 addr
, u32 data
)
102 nvkm_debug(&memx
->pmu
->subdev
, "R[%06x] = %08x\n", addr
, data
);
103 memx_cmd(memx
, MEMX_WR32
, 2, (u32
[]){ addr
, data
});
107 nvkm_memx_wait(struct nvkm_memx
*memx
,
108 u32 addr
, u32 mask
, u32 data
, u32 nsec
)
110 nvkm_debug(&memx
->pmu
->subdev
, "R[%06x] & %08x == %08x, %d us\n",
111 addr
, mask
, data
, nsec
);
112 memx_cmd(memx
, MEMX_WAIT
, 4, (u32
[]){ addr
, mask
, data
, nsec
});
113 memx_out(memx
); /* fuc can't handle multiple */
117 nvkm_memx_nsec(struct nvkm_memx
*memx
, u32 nsec
)
119 nvkm_debug(&memx
->pmu
->subdev
, " DELAY = %d ns\n", nsec
);
120 memx_cmd(memx
, MEMX_DELAY
, 1, (u32
[]){ nsec
});
121 memx_out(memx
); /* fuc can't handle multiple */
125 nvkm_memx_wait_vblank(struct nvkm_memx
*memx
)
127 struct nvkm_subdev
*subdev
= &memx
->pmu
->subdev
;
128 struct nvkm_device
*device
= subdev
->device
;
129 u32 heads
, x
, y
, px
= 0;
132 if (device
->chipset
< 0xd0) {
133 heads
= nvkm_rd32(device
, 0x610050);
134 for (i
= 0; i
< 2; i
++) {
135 /* Heuristic: sync to head with biggest resolution */
136 if (heads
& (2 << (i
<< 3))) {
137 x
= nvkm_rd32(device
, 0x610b40 + (0x540 * i
));
138 y
= (x
& 0xffff0000) >> 16;
149 nvkm_debug(subdev
, "WAIT VBLANK !NO ACTIVE HEAD\n");
153 nvkm_debug(subdev
, "WAIT VBLANK HEAD%d\n", head_sync
);
154 memx_cmd(memx
, MEMX_VBLANK
, 1, (u32
[]){ head_sync
});
155 memx_out(memx
); /* fuc can't handle multiple */
159 nvkm_memx_train(struct nvkm_memx
*memx
)
161 nvkm_debug(&memx
->pmu
->subdev
, " MEM TRAIN\n");
162 memx_cmd(memx
, MEMX_TRAIN
, 0, NULL
);
166 nvkm_memx_train_result(struct nvkm_pmu
*pmu
, u32
*res
, int rsize
)
168 struct nvkm_device
*device
= pmu
->subdev
.device
;
169 u32 reply
[2], base
, size
, i
;
172 ret
= nvkm_pmu_send(pmu
, reply
, PROC_MEMX
, MEMX_MSG_INFO
,
178 size
= reply
[1] >> 2;
182 /* read the packet */
183 nvkm_wr32(device
, 0x10a1c0, 0x02000000 | base
);
185 for (i
= 0; i
< size
; i
++)
186 res
[i
] = nvkm_rd32(device
, 0x10a1c4);
192 nvkm_memx_block(struct nvkm_memx
*memx
)
194 nvkm_debug(&memx
->pmu
->subdev
, " HOST BLOCKED\n");
195 memx_cmd(memx
, MEMX_ENTER
, 0, NULL
);
199 nvkm_memx_unblock(struct nvkm_memx
*memx
)
201 nvkm_debug(&memx
->pmu
->subdev
, " HOST UNBLOCKED\n");
202 memx_cmd(memx
, MEMX_LEAVE
, 0, NULL
);